aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Framework')
-rw-r--r--OpenSim/Framework/AgentCircuitData.cs26
-rw-r--r--OpenSim/Framework/Animation.cs19
-rw-r--r--OpenSim/Framework/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/AssetLoader/Filesystem/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/BasicDOSProtector.cs275
-rw-r--r--OpenSim/Framework/BlockingQueue.cs36
-rw-r--r--OpenSim/Framework/CachedTextureEventArg.cs46
-rw-r--r--OpenSim/Framework/ChildAgentDataUpdate.cs20
-rw-r--r--OpenSim/Framework/CircularBuffer.cs312
-rw-r--r--OpenSim/Framework/ClientInfo.cs11
-rw-r--r--OpenSim/Framework/Communications/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/ConfigSettings.cs1
-rw-r--r--OpenSim/Framework/Configuration/HTTP/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/Configuration/XML/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/Configuration/XML/XmlConfiguration.cs2
-rw-r--r--OpenSim/Framework/Console/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/Console/ConsoleUtil.cs47
-rw-r--r--OpenSim/Framework/Console/LocalConsole.cs15
-rw-r--r--OpenSim/Framework/Console/RemoteConsole.cs2
-rw-r--r--OpenSim/Framework/Constants.cs11
-rw-r--r--OpenSim/Framework/DAMap.cs295
-rw-r--r--OpenSim/Framework/DOMap.cs8
-rw-r--r--OpenSim/Framework/EstateSettings.cs1
-rw-r--r--OpenSim/Framework/IClientAPI.cs11
-rw-r--r--OpenSim/Framework/IImprovedAssetCache.cs26
-rw-r--r--OpenSim/Framework/IPeople.cs47
-rw-r--r--OpenSim/Framework/IScene.cs21
-rw-r--r--OpenSim/Framework/InventoryItemBase.cs2
-rw-r--r--OpenSim/Framework/Location.cs16
-rw-r--r--OpenSim/Framework/Monitoring/BaseStatsCollector.cs14
-rw-r--r--OpenSim/Framework/Monitoring/Checks/Check.cs118
-rw-r--r--OpenSim/Framework/Monitoring/ChecksManager.cs262
-rw-r--r--OpenSim/Framework/Monitoring/MemoryWatchdog.cs8
-rw-r--r--OpenSim/Framework/Monitoring/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/Monitoring/ServerStatsCollector.cs349
-rw-r--r--OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs25
-rwxr-xr-xOpenSim/Framework/Monitoring/Stats/CounterStat.cs163
-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.cs79
-rw-r--r--OpenSim/Framework/Monitoring/StatsLogger.cs108
-rw-r--r--OpenSim/Framework/Monitoring/StatsManager.cs334
-rw-r--r--OpenSim/Framework/Monitoring/Watchdog.cs1
-rw-r--r--OpenSim/Framework/PermissionsUtil.cs87
-rw-r--r--OpenSim/Framework/PrimitiveBaseShape.cs11
-rw-r--r--OpenSim/Framework/RegionFlags.cs3
-rw-r--r--OpenSim/Framework/RegionInfo.cs172
-rw-r--r--OpenSim/Framework/RegionLoader/Filesystem/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/RegionLoader/Web/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/RegionSettings.cs25
-rw-r--r--OpenSim/Framework/SLUtil.cs70
-rw-r--r--OpenSim/Framework/Serialization/ArchiveConstants.cs3
-rw-r--r--OpenSim/Framework/Serialization/External/UserInventoryItemSerializer.cs2
-rw-r--r--OpenSim/Framework/Serialization/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/Servers/BaseOpenSimServer.cs50
-rw-r--r--OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs59
-rw-r--r--OpenSim/Framework/Servers/HttpServer/BaseOutputStreamHandler.cs60
-rw-r--r--OpenSim/Framework/Servers/HttpServer/BaseRequestHandler.cs4
-rw-r--r--OpenSim/Framework/Servers/HttpServer/BaseStreamHandler.cs27
-rw-r--r--OpenSim/Framework/Servers/HttpServer/BaseStreamHandlerBasicDOSProtector.cs107
-rw-r--r--OpenSim/Framework/Servers/HttpServer/BinaryStreamHandler.cs2
-rw-r--r--OpenSim/Framework/Servers/HttpServer/GenericHTTPBasicDOSProtector.cs119
-rw-r--r--OpenSim/Framework/Servers/HttpServer/Interfaces/IStreamHandler.cs15
-rw-r--r--OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs18
-rw-r--r--OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs45
-rw-r--r--OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs16
-rw-r--r--OpenSim/Framework/Servers/HttpServer/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/Servers/HttpServer/RestDeserialiseHandler.cs4
-rw-r--r--OpenSim/Framework/Servers/HttpServer/RestSessionService.cs13
-rw-r--r--OpenSim/Framework/Servers/HttpServer/RestStreamHandler.cs2
-rw-r--r--OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs87
-rw-r--r--OpenSim/Framework/Servers/HttpServer/XmlRpcBasicDOSProtector.cs91
-rw-r--r--OpenSim/Framework/Servers/MainServer.cs13
-rw-r--r--OpenSim/Framework/Servers/ServerBase.cs254
-rw-r--r--OpenSim/Framework/Servers/VersionInfo.cs2
-rw-r--r--OpenSim/Framework/TaskInventoryItem.cs2
-rw-r--r--OpenSim/Framework/Tests/LocationTest.cs21
-rw-r--r--OpenSim/Framework/Tests/MundaneFrameworkTests.cs2
-rw-r--r--OpenSim/Framework/Tests/UtilTest.cs82
-rw-r--r--OpenSim/Framework/UserProfiles.cs117
-rw-r--r--OpenSim/Framework/Util.cs192
-rw-r--r--OpenSim/Framework/WebUtil.cs82
82 files changed, 4118 insertions, 663 deletions
diff --git a/OpenSim/Framework/AgentCircuitData.cs b/OpenSim/Framework/AgentCircuitData.cs
index ffcc584..f2fe494 100644
--- a/OpenSim/Framework/AgentCircuitData.cs
+++ b/OpenSim/Framework/AgentCircuitData.cs
@@ -128,7 +128,31 @@ namespace OpenSim.Framework
128 /// <summary> 128 /// <summary>
129 /// Viewer's version string as reported by the viewer at login 129 /// Viewer's version string as reported by the viewer at login
130 /// </summary> 130 /// </summary>
131 public string Viewer; 131 private string m_viewerInternal;
132
133 /// <summary>
134 /// Viewer's version string
135 /// </summary>
136 public string Viewer
137 {
138 set { m_viewerInternal = value; }
139
140 // Try to return consistent viewer string taking into account
141 // that viewers have chaagned how version is reported
142 // See http://opensimulator.org/mantis/view.php?id=6851
143 get
144 {
145 // Old style version string contains viewer name followed by a space followed by a version number
146 if (m_viewerInternal == null || m_viewerInternal.Contains(" "))
147 {
148 return m_viewerInternal;
149 }
150 else // New style version contains no spaces, just version number
151 {
152 return Channel + " " + m_viewerInternal;
153 }
154 }
155 }
132 156
133 /// <summary> 157 /// <summary>
134 /// The channel strinf sent by the viewer at login 158 /// The channel strinf sent by the viewer at login
diff --git a/OpenSim/Framework/Animation.cs b/OpenSim/Framework/Animation.cs
index 232f5a1..3425505 100644
--- a/OpenSim/Framework/Animation.cs
+++ b/OpenSim/Framework/Animation.cs
@@ -120,5 +120,24 @@ namespace OpenSim.Framework
120 sequenceNum = args["seq_num"].AsInteger(); 120 sequenceNum = args["seq_num"].AsInteger();
121 } 121 }
122 122
123 public override bool Equals(object obj)
124 {
125 Animation other = obj as Animation;
126 if (other != null)
127 {
128 return (other.AnimID.Equals(this.AnimID)
129 && other.SequenceNum == this.SequenceNum
130 && other.ObjectID.Equals(this.ObjectID) );
131 }
132 return base.Equals(obj);
133 }
134
135 public override string ToString()
136 {
137 return "AnimID=" + AnimID.ToString()
138 + "/seq=" + SequenceNum.ToString()
139 + "/objID=" + ObjectID.ToString();
140 }
141
123 } 142 }
124} 143}
diff --git a/OpenSim/Framework/AssemblyInfo.cs b/OpenSim/Framework/AssemblyInfo.cs
index d6b4e6a..287b988 100644
--- a/OpenSim/Framework/AssemblyInfo.cs
+++ b/OpenSim/Framework/AssemblyInfo.cs
@@ -59,4 +59,4 @@ using System.Runtime.InteropServices;
59// Revision 59// Revision
60// 60//
61 61
62[assembly : AssemblyVersion("0.7.6.*")] 62[assembly : AssemblyVersion("0.8.0.*")]
diff --git a/OpenSim/Framework/AssetLoader/Filesystem/Properties/AssemblyInfo.cs b/OpenSim/Framework/AssetLoader/Filesystem/Properties/AssemblyInfo.cs
index feffa26..11fece3 100644
--- a/OpenSim/Framework/AssetLoader/Filesystem/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/AssetLoader/Filesystem/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Framework/BasicDOSProtector.cs b/OpenSim/Framework/BasicDOSProtector.cs
new file mode 100644
index 0000000..89bfa94
--- /dev/null
+++ b/OpenSim/Framework/BasicDOSProtector.cs
@@ -0,0 +1,275 @@
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 */
27using System;
28using System.Collections.Generic;
29using System.Reflection;
30using log4net;
31
32namespace OpenSim.Framework
33{
34
35 public class BasicDOSProtector
36 {
37 public enum ThrottleAction
38 {
39 DoThrottledMethod,
40 DoThrow
41 }
42 private readonly CircularBuffer<int> _generalRequestTimes; // General request checker
43 private readonly BasicDosProtectorOptions _options;
44 private readonly Dictionary<string, CircularBuffer<int>> _deeperInspection; // per client request checker
45 private readonly Dictionary<string, int> _tempBlocked; // blocked list
46 private readonly Dictionary<string, int> _sessions;
47 private readonly System.Timers.Timer _forgetTimer; // Cleanup timer
48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
49 private readonly System.Threading.ReaderWriterLockSlim _blockLockSlim = new System.Threading.ReaderWriterLockSlim();
50 private readonly System.Threading.ReaderWriterLockSlim _sessionLockSlim = new System.Threading.ReaderWriterLockSlim();
51 public BasicDOSProtector(BasicDosProtectorOptions options)
52 {
53 _generalRequestTimes = new CircularBuffer<int>(options.MaxRequestsInTimeframe + 1, true);
54 _generalRequestTimes.Put(0);
55 _options = options;
56 _deeperInspection = new Dictionary<string, CircularBuffer<int>>();
57 _tempBlocked = new Dictionary<string, int>();
58 _sessions = new Dictionary<string, int>();
59 _forgetTimer = new System.Timers.Timer();
60 _forgetTimer.Elapsed += delegate
61 {
62 _forgetTimer.Enabled = false;
63
64 List<string> removes = new List<string>();
65 _blockLockSlim.EnterReadLock();
66 foreach (string str in _tempBlocked.Keys)
67 {
68 if (
69 Util.EnvironmentTickCountSubtract(Util.EnvironmentTickCount(),
70 _tempBlocked[str]) > 0)
71 removes.Add(str);
72 }
73 _blockLockSlim.ExitReadLock();
74 lock (_deeperInspection)
75 {
76 _blockLockSlim.EnterWriteLock();
77 for (int i = 0; i < removes.Count; i++)
78 {
79 _tempBlocked.Remove(removes[i]);
80 _deeperInspection.Remove(removes[i]);
81 _sessions.Remove(removes[i]);
82 }
83 _blockLockSlim.ExitWriteLock();
84 }
85 foreach (string str in removes)
86 {
87 m_log.InfoFormat("[{0}] client: {1} is no longer blocked.",
88 _options.ReportingName, str);
89 }
90 _blockLockSlim.EnterReadLock();
91 if (_tempBlocked.Count > 0)
92 _forgetTimer.Enabled = true;
93 _blockLockSlim.ExitReadLock();
94 };
95
96 _forgetTimer.Interval = _options.ForgetTimeSpan.TotalMilliseconds;
97 }
98
99 /// <summary>
100 /// Given a string Key, Returns if that context is blocked
101 /// </summary>
102 /// <param name="key">A Key identifying the context</param>
103 /// <returns>bool Yes or No, True or False for blocked</returns>
104 public bool IsBlocked(string key)
105 {
106 bool ret = false;
107 _blockLockSlim.EnterReadLock();
108 ret = _tempBlocked.ContainsKey(key);
109 _blockLockSlim.ExitReadLock();
110 return ret;
111 }
112
113 /// <summary>
114 /// Process the velocity of this context
115 /// </summary>
116 /// <param name="key"></param>
117 /// <param name="endpoint"></param>
118 /// <returns></returns>
119 public bool Process(string key, string endpoint)
120 {
121 if (_options.MaxRequestsInTimeframe < 1 || _options.RequestTimeSpan.TotalMilliseconds < 1)
122 return true;
123
124 string clientstring = key;
125
126 _blockLockSlim.EnterReadLock();
127 if (_tempBlocked.ContainsKey(clientstring))
128 {
129 _blockLockSlim.ExitReadLock();
130
131 if (_options.ThrottledAction == ThrottleAction.DoThrottledMethod)
132 return false;
133 else
134 throw new System.Security.SecurityException("Throttled");
135 }
136
137 _blockLockSlim.ExitReadLock();
138
139 lock (_generalRequestTimes)
140 _generalRequestTimes.Put(Util.EnvironmentTickCount());
141
142 if (_options.MaxConcurrentSessions > 0)
143 {
144 int sessionscount = 0;
145
146 _sessionLockSlim.EnterReadLock();
147 if (_sessions.ContainsKey(key))
148 sessionscount = _sessions[key];
149 _sessionLockSlim.ExitReadLock();
150
151 if (sessionscount > _options.MaxConcurrentSessions)
152 {
153 // Add to blocking and cleanup methods
154 lock (_deeperInspection)
155 {
156 _blockLockSlim.EnterWriteLock();
157 if (!_tempBlocked.ContainsKey(clientstring))
158 {
159 _tempBlocked.Add(clientstring,
160 Util.EnvironmentTickCount() +
161 (int) _options.ForgetTimeSpan.TotalMilliseconds);
162 _forgetTimer.Enabled = true;
163 m_log.WarnFormat("[{0}]: client: {1} is blocked for {2} milliseconds based on concurrency, X-ForwardedForAllowed status is {3}, endpoint:{4}", _options.ReportingName, clientstring, _options.ForgetTimeSpan.TotalMilliseconds, _options.AllowXForwardedFor, endpoint);
164
165 }
166 else
167 _tempBlocked[clientstring] = Util.EnvironmentTickCount() +
168 (int) _options.ForgetTimeSpan.TotalMilliseconds;
169 _blockLockSlim.ExitWriteLock();
170
171 }
172
173
174 }
175 else
176 ProcessConcurrency(key, endpoint);
177 }
178 if (_generalRequestTimes.Size == _generalRequestTimes.Capacity &&
179 (Util.EnvironmentTickCountSubtract(Util.EnvironmentTickCount(), _generalRequestTimes.Get()) <
180 _options.RequestTimeSpan.TotalMilliseconds))
181 {
182 //Trigger deeper inspection
183 if (DeeperInspection(key, endpoint))
184 return true;
185 if (_options.ThrottledAction == ThrottleAction.DoThrottledMethod)
186 return false;
187 else
188 throw new System.Security.SecurityException("Throttled");
189 }
190 return true;
191 }
192 private void ProcessConcurrency(string key, string endpoint)
193 {
194 _sessionLockSlim.EnterWriteLock();
195 if (_sessions.ContainsKey(key))
196 _sessions[key] = _sessions[key] + 1;
197 else
198 _sessions.Add(key,1);
199 _sessionLockSlim.ExitWriteLock();
200 }
201 public void ProcessEnd(string key, string endpoint)
202 {
203 _sessionLockSlim.EnterWriteLock();
204 if (_sessions.ContainsKey(key))
205 {
206 _sessions[key]--;
207 if (_sessions[key] <= 0)
208 _sessions.Remove(key);
209 }
210 else
211 _sessions.Add(key, 1);
212
213 _sessionLockSlim.ExitWriteLock();
214 }
215
216 /// <summary>
217 /// At this point, the rate limiting code needs to track 'per user' velocity.
218 /// </summary>
219 /// <param name="key">Context Key, string representing a rate limiting context</param>
220 /// <param name="endpoint"></param>
221 /// <returns></returns>
222 private bool DeeperInspection(string key, string endpoint)
223 {
224 lock (_deeperInspection)
225 {
226 string clientstring = key;
227
228
229 if (_deeperInspection.ContainsKey(clientstring))
230 {
231 _deeperInspection[clientstring].Put(Util.EnvironmentTickCount());
232 if (_deeperInspection[clientstring].Size == _deeperInspection[clientstring].Capacity &&
233 (Util.EnvironmentTickCountSubtract(Util.EnvironmentTickCount(), _deeperInspection[clientstring].Get()) <
234 _options.RequestTimeSpan.TotalMilliseconds))
235 {
236 //Looks like we're over the limit
237 _blockLockSlim.EnterWriteLock();
238 if (!_tempBlocked.ContainsKey(clientstring))
239 _tempBlocked.Add(clientstring, Util.EnvironmentTickCount() + (int)_options.ForgetTimeSpan.TotalMilliseconds);
240 else
241 _tempBlocked[clientstring] = Util.EnvironmentTickCount() + (int)_options.ForgetTimeSpan.TotalMilliseconds;
242 _blockLockSlim.ExitWriteLock();
243
244 m_log.WarnFormat("[{0}]: client: {1} is blocked for {2} milliseconds, X-ForwardedForAllowed status is {3}, endpoint:{4}", _options.ReportingName, clientstring, _options.ForgetTimeSpan.TotalMilliseconds, _options.AllowXForwardedFor, endpoint);
245
246 return false;
247 }
248 //else
249 // return true;
250 }
251 else
252 {
253 _deeperInspection.Add(clientstring, new CircularBuffer<int>(_options.MaxRequestsInTimeframe + 1, true));
254 _deeperInspection[clientstring].Put(Util.EnvironmentTickCount());
255 _forgetTimer.Enabled = true;
256 }
257
258 }
259 return true;
260 }
261
262 }
263
264
265 public class BasicDosProtectorOptions
266 {
267 public int MaxRequestsInTimeframe;
268 public TimeSpan RequestTimeSpan;
269 public TimeSpan ForgetTimeSpan;
270 public bool AllowXForwardedFor;
271 public string ReportingName = "BASICDOSPROTECTOR";
272 public BasicDOSProtector.ThrottleAction ThrottledAction = BasicDOSProtector.ThrottleAction.DoThrottledMethod;
273 public int MaxConcurrentSessions;
274 }
275}
diff --git a/OpenSim/Framework/BlockingQueue.cs b/OpenSim/Framework/BlockingQueue.cs
index 3658161..3e90fac 100644
--- a/OpenSim/Framework/BlockingQueue.cs
+++ b/OpenSim/Framework/BlockingQueue.cs
@@ -58,7 +58,7 @@ namespace OpenSim.Framework
58 { 58 {
59 lock (m_queueSync) 59 lock (m_queueSync)
60 { 60 {
61 if (m_queue.Count < 1 && m_pqueue.Count < 1) 61 while (m_queue.Count < 1 && m_pqueue.Count < 1)
62 { 62 {
63 Monitor.Wait(m_queueSync); 63 Monitor.Wait(m_queueSync);
64 } 64 }
@@ -76,9 +76,10 @@ namespace OpenSim.Framework
76 { 76 {
77 lock (m_queueSync) 77 lock (m_queueSync)
78 { 78 {
79 if (m_queue.Count < 1 && m_pqueue.Count < 1) 79 bool success = true;
80 while (m_queue.Count < 1 && m_pqueue.Count < 1 && success)
80 { 81 {
81 Monitor.Wait(m_queueSync, msTimeout); 82 success = Monitor.Wait(m_queueSync, msTimeout);
82 } 83 }
83 84
84 if (m_pqueue.Count > 0) 85 if (m_pqueue.Count > 0)
@@ -89,8 +90,17 @@ namespace OpenSim.Framework
89 } 90 }
90 } 91 }
91 92
93 /// <summary>
94 /// Indicate whether this queue contains the given item.
95 /// </summary>
96 /// <remarks>
97 /// This method is not thread-safe. Do not rely on the result without consistent external locking.
98 /// </remarks>
92 public bool Contains(T item) 99 public bool Contains(T item)
93 { 100 {
101 if (m_queue.Count < 1 && m_pqueue.Count < 1)
102 return false;
103
94 lock (m_queueSync) 104 lock (m_queueSync)
95 { 105 {
96 if (m_pqueue.Contains(item)) 106 if (m_pqueue.Contains(item))
@@ -99,16 +109,28 @@ namespace OpenSim.Framework
99 } 109 }
100 } 110 }
101 111
112 /// <summary>
113 /// Return a count of the number of requests on this queue.
114 /// </summary>
115 /// <remarks>
116 /// This method is not thread-safe. Do not rely on the result without consistent external locking.
117 /// </remarks>
102 public int Count() 118 public int Count()
103 { 119 {
104 lock (m_queueSync) 120 return m_queue.Count + m_pqueue.Count;
105 {
106 return m_queue.Count+m_pqueue.Count;
107 }
108 } 121 }
109 122
123 /// <summary>
124 /// Return the array of items on this queue.
125 /// </summary>
126 /// <remarks>
127 /// This method is not thread-safe. Do not rely on the result without consistent external locking.
128 /// </remarks>
110 public T[] GetQueueArray() 129 public T[] GetQueueArray()
111 { 130 {
131 if (m_queue.Count < 1 && m_pqueue.Count < 1)
132 return new T[0];
133
112 lock (m_queueSync) 134 lock (m_queueSync)
113 { 135 {
114 return m_queue.ToArray(); 136 return m_queue.ToArray();
diff --git a/OpenSim/Framework/CachedTextureEventArg.cs b/OpenSim/Framework/CachedTextureEventArg.cs
new file mode 100644
index 0000000..239fc56
--- /dev/null
+++ b/OpenSim/Framework/CachedTextureEventArg.cs
@@ -0,0 +1,46 @@
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.Text;
30using OpenMetaverse;
31
32namespace OpenSim.Framework
33{
34 public class CachedTextureRequestArg
35 {
36 public int BakedTextureIndex;
37 public UUID WearableHashID;
38 }
39
40 public class CachedTextureResponseArg
41 {
42 public int BakedTextureIndex;
43 public UUID BakedTextureID;
44 public String HostName;
45 }
46}
diff --git a/OpenSim/Framework/ChildAgentDataUpdate.cs b/OpenSim/Framework/ChildAgentDataUpdate.cs
index 8c32734..2a8e67d 100644
--- a/OpenSim/Framework/ChildAgentDataUpdate.cs
+++ b/OpenSim/Framework/ChildAgentDataUpdate.cs
@@ -171,9 +171,10 @@ namespace OpenSim.Framework
171 /// Soon to be decommissioned 171 /// Soon to be decommissioned
172 /// </summary> 172 /// </summary>
173 /// <param name="cAgent"></param> 173 /// <param name="cAgent"></param>
174 public void CopyFrom(ChildAgentDataUpdate cAgent) 174 public void CopyFrom(ChildAgentDataUpdate cAgent, UUID sid)
175 { 175 {
176 AgentID = new UUID(cAgent.AgentID); 176 AgentID = new UUID(cAgent.AgentID);
177 SessionID = sid;
177 178
178 // next: ??? 179 // next: ???
179 Size = new Vector3(); 180 Size = new Vector3();
@@ -291,7 +292,13 @@ namespace OpenSim.Framework
291 public Vector3 AtAxis; 292 public Vector3 AtAxis;
292 public Vector3 LeftAxis; 293 public Vector3 LeftAxis;
293 public Vector3 UpAxis; 294 public Vector3 UpAxis;
294 public bool ChangedGrid; 295
296 /// <summary>
297 /// Signal on a V2 teleport that Scene.IncomingChildAgentDataUpdate(AgentData ad) should wait for the
298 /// scene presence to become root (triggered when the viewer sends a CompleteAgentMovement UDP packet after
299 /// establishing the connection triggered by it's receipt of a TeleportFinish EQ message).
300 /// </summary>
301 public bool SenderWantsToWaitForRoot;
295 302
296 public float Far; 303 public float Far;
297 public float Aspect; 304 public float Aspect;
@@ -362,8 +369,9 @@ namespace OpenSim.Framework
362 args["left_axis"] = OSD.FromString(LeftAxis.ToString()); 369 args["left_axis"] = OSD.FromString(LeftAxis.ToString());
363 args["up_axis"] = OSD.FromString(UpAxis.ToString()); 370 args["up_axis"] = OSD.FromString(UpAxis.ToString());
364 371
365 372 //backwards compatibility
366 args["changed_grid"] = OSD.FromBoolean(ChangedGrid); 373 args["changed_grid"] = OSD.FromBoolean(SenderWantsToWaitForRoot);
374 args["wait_for_root"] = OSD.FromBoolean(SenderWantsToWaitForRoot);
367 args["far"] = OSD.FromReal(Far); 375 args["far"] = OSD.FromReal(Far);
368 args["aspect"] = OSD.FromReal(Aspect); 376 args["aspect"] = OSD.FromReal(Aspect);
369 377
@@ -536,8 +544,8 @@ namespace OpenSim.Framework
536 if (args["up_axis"] != null) 544 if (args["up_axis"] != null)
537 Vector3.TryParse(args["up_axis"].AsString(), out AtAxis); 545 Vector3.TryParse(args["up_axis"].AsString(), out AtAxis);
538 546
539 if (args["changed_grid"] != null) 547 if (args.ContainsKey("wait_for_root") && args["wait_for_root"] != null)
540 ChangedGrid = args["changed_grid"].AsBoolean(); 548 SenderWantsToWaitForRoot = args["wait_for_root"].AsBoolean();
541 549
542 if (args["far"] != null) 550 if (args["far"] != null)
543 Far = (float)(args["far"].AsReal()); 551 Far = (float)(args["far"].AsReal());
diff --git a/OpenSim/Framework/CircularBuffer.cs b/OpenSim/Framework/CircularBuffer.cs
new file mode 100644
index 0000000..e919337
--- /dev/null
+++ b/OpenSim/Framework/CircularBuffer.cs
@@ -0,0 +1,312 @@
1/*
2Copyright (c) 2012, Alex Regueiro
3All rights reserved.
4Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
5following conditions are met:
6
7Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
8Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer
9in the documentation and/or other materials provided with the distribution.
10
11THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
12BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
13IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
14OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
15OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
16OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
17POSSIBILITY OF SUCH DAMAGE.
18*/
19using System;
20using System.Collections;
21using System.Collections.Generic;
22using System.Threading;
23
24namespace OpenSim.Framework
25{
26 public class CircularBuffer<T> : ICollection<T>, IEnumerable<T>, ICollection, IEnumerable
27 {
28 private int capacity;
29 private int size;
30 private int head;
31 private int tail;
32 private T[] buffer;
33
34 [NonSerialized()]
35 private object syncRoot;
36
37 public CircularBuffer(int capacity)
38 : this(capacity, false)
39 {
40 }
41
42 public CircularBuffer(int capacity, bool allowOverflow)
43 {
44 if (capacity < 0)
45 throw new ArgumentException("Needs to have at least 1","capacity");
46
47 this.capacity = capacity;
48 size = 0;
49 head = 0;
50 tail = 0;
51 buffer = new T[capacity];
52 AllowOverflow = allowOverflow;
53 }
54
55 public bool AllowOverflow
56 {
57 get;
58 set;
59 }
60
61 public int Capacity
62 {
63 get { return capacity; }
64 set
65 {
66 if (value == capacity)
67 return;
68
69 if (value < size)
70 throw new ArgumentOutOfRangeException("value","Capacity is too small.");
71
72 var dst = new T[value];
73 if (size > 0)
74 CopyTo(dst);
75 buffer = dst;
76
77 capacity = value;
78 }
79 }
80
81 public int Size
82 {
83 get { return size; }
84 }
85
86 public bool Contains(T item)
87 {
88 int bufferIndex = head;
89 var comparer = EqualityComparer<T>.Default;
90 for (int i = 0; i < size; i++, bufferIndex++)
91 {
92 if (bufferIndex == capacity)
93 bufferIndex = 0;
94
95 if (item == null && buffer[bufferIndex] == null)
96 return true;
97 else if ((buffer[bufferIndex] != null) &&
98 comparer.Equals(buffer[bufferIndex], item))
99 return true;
100 }
101
102 return false;
103 }
104
105 public void Clear()
106 {
107 size = 0;
108 head = 0;
109 tail = 0;
110 }
111
112 public int Put(T[] src)
113 {
114 return Put(src, 0, src.Length);
115 }
116
117 public int Put(T[] src, int offset, int count)
118 {
119 if (!AllowOverflow && count > capacity - size)
120 throw new InvalidOperationException("Buffer Overflow");
121
122 int srcIndex = offset;
123 for (int i = 0; i < count; i++, tail++, srcIndex++)
124 {
125 if (tail == capacity)
126 tail = 0;
127 buffer[tail] = src[srcIndex];
128 }
129 size = Math.Min(size + count, capacity);
130 return count;
131 }
132
133 public void Put(T item)
134 {
135 if (!AllowOverflow && size == capacity)
136 throw new InvalidOperationException("Buffer Overflow");
137
138 buffer[tail] = item;
139 if (++tail == capacity)
140 tail = 0;
141 size++;
142 }
143
144 public void Skip(int count)
145 {
146 head += count;
147 if (head >= capacity)
148 head -= capacity;
149 }
150
151 public T[] Get(int count)
152 {
153 var dst = new T[count];
154 Get(dst);
155 return dst;
156 }
157
158 public int Get(T[] dst)
159 {
160 return Get(dst, 0, dst.Length);
161 }
162
163 public int Get(T[] dst, int offset, int count)
164 {
165 int realCount = Math.Min(count, size);
166 int dstIndex = offset;
167 for (int i = 0; i < realCount; i++, head++, dstIndex++)
168 {
169 if (head == capacity)
170 head = 0;
171 dst[dstIndex] = buffer[head];
172 }
173 size -= realCount;
174 return realCount;
175 }
176
177 public T Get()
178 {
179 if (size == 0)
180 throw new InvalidOperationException("Buffer Empty");
181
182 var item = buffer[head];
183 if (++head == capacity)
184 head = 0;
185 size--;
186 return item;
187 }
188
189 public void CopyTo(T[] array)
190 {
191 CopyTo(array, 0);
192 }
193
194 public void CopyTo(T[] array, int arrayIndex)
195 {
196 CopyTo(0, array, arrayIndex, size);
197 }
198
199 public void CopyTo(int index, T[] array, int arrayIndex, int count)
200 {
201 if (count > size)
202 throw new ArgumentOutOfRangeException("count", "Count Too Large");
203
204 int bufferIndex = head;
205 for (int i = 0; i < count; i++, bufferIndex++, arrayIndex++)
206 {
207 if (bufferIndex == capacity)
208 bufferIndex = 0;
209 array[arrayIndex] = buffer[bufferIndex];
210 }
211 }
212
213 public IEnumerator<T> GetEnumerator()
214 {
215 int bufferIndex = head;
216 for (int i = 0; i < size; i++, bufferIndex++)
217 {
218 if (bufferIndex == capacity)
219 bufferIndex = 0;
220
221 yield return buffer[bufferIndex];
222 }
223 }
224
225 public T[] GetBuffer()
226 {
227 return buffer;
228 }
229
230 public T[] ToArray()
231 {
232 var dst = new T[size];
233 CopyTo(dst);
234 return dst;
235 }
236
237 #region ICollection<T> Members
238
239 int ICollection<T>.Count
240 {
241 get { return Size; }
242 }
243
244 bool ICollection<T>.IsReadOnly
245 {
246 get { return false; }
247 }
248
249 void ICollection<T>.Add(T item)
250 {
251 Put(item);
252 }
253
254 bool ICollection<T>.Remove(T item)
255 {
256 if (size == 0)
257 return false;
258
259 Get();
260 return true;
261 }
262
263 #endregion
264
265 #region IEnumerable<T> Members
266
267 IEnumerator<T> IEnumerable<T>.GetEnumerator()
268 {
269 return GetEnumerator();
270 }
271
272 #endregion
273
274 #region ICollection Members
275
276 int ICollection.Count
277 {
278 get { return Size; }
279 }
280
281 bool ICollection.IsSynchronized
282 {
283 get { return false; }
284 }
285
286 object ICollection.SyncRoot
287 {
288 get
289 {
290 if (syncRoot == null)
291 Interlocked.CompareExchange(ref syncRoot, new object(), null);
292 return syncRoot;
293 }
294 }
295
296 void ICollection.CopyTo(Array array, int arrayIndex)
297 {
298 CopyTo((T[])array, arrayIndex);
299 }
300
301 #endregion
302
303 #region IEnumerable Members
304
305 IEnumerator IEnumerable.GetEnumerator()
306 {
307 return (IEnumerator)GetEnumerator();
308 }
309
310 #endregion
311 }
312}
diff --git a/OpenSim/Framework/ClientInfo.cs b/OpenSim/Framework/ClientInfo.cs
index 62acb70..9021315 100644
--- a/OpenSim/Framework/ClientInfo.cs
+++ b/OpenSim/Framework/ClientInfo.cs
@@ -33,12 +33,13 @@ namespace OpenSim.Framework
33{ 33{
34 public class ClientInfo 34 public class ClientInfo
35 { 35 {
36 public AgentCircuitData agentcircuit; 36 public readonly DateTime StartedTime = DateTime.Now;
37 public AgentCircuitData agentcircuit = null;
37 38
38 public Dictionary<uint, byte[]> needAck; 39 public Dictionary<uint, byte[]> needAck;
39 40
40 public List<byte[]> out_packets; 41 public List<byte[]> out_packets = new List<byte[]>();
41 public Dictionary<uint, uint> pendingAcks; 42 public Dictionary<uint, uint> pendingAcks = new Dictionary<uint,uint>();
42 public EndPoint proxyEP; 43 public EndPoint proxyEP;
43 44
44 public uint sequence; 45 public uint sequence;
@@ -53,5 +54,9 @@ namespace OpenSim.Framework
53 public int assetThrottle; 54 public int assetThrottle;
54 public int textureThrottle; 55 public int textureThrottle;
55 public int totalThrottle; 56 public int totalThrottle;
57
58 public Dictionary<string, int> SyncRequests = new Dictionary<string,int>();
59 public Dictionary<string, int> AsyncRequests = new Dictionary<string,int>();
60 public Dictionary<string, int> GenericRequests = new Dictionary<string,int>();
56 } 61 }
57} 62}
diff --git a/OpenSim/Framework/Communications/Properties/AssemblyInfo.cs b/OpenSim/Framework/Communications/Properties/AssemblyInfo.cs
index df8eb52..09611fa 100644
--- a/OpenSim/Framework/Communications/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/Communications/Properties/AssemblyInfo.cs
@@ -61,5 +61,5 @@ using System.Runtime.InteropServices;
61// You can specify all the values or you can default the Revision and Build Numbers 61// You can specify all the values or you can default the Revision and Build Numbers
62// by using the '*' as shown below: 62// by using the '*' as shown below:
63 63
64[assembly : AssemblyVersion("0.7.6.*")] 64[assembly : AssemblyVersion("0.8.0.*")]
65 65
diff --git a/OpenSim/Framework/ConfigSettings.cs b/OpenSim/Framework/ConfigSettings.cs
index 002a371..108a3e4 100644
--- a/OpenSim/Framework/ConfigSettings.cs
+++ b/OpenSim/Framework/ConfigSettings.cs
@@ -31,7 +31,6 @@ namespace OpenSim.Framework
31 { 31 {
32 public string PhysicsEngine { get; set; } 32 public string PhysicsEngine { get; set; }
33 public string MeshEngineName { get; set; } 33 public string MeshEngineName { get; set; }
34 public string StorageDll { get; set; }
35 public string ClientstackDll { get; set; } 34 public string ClientstackDll { get; set; }
36 public string LibrariesXMLFile { get; set; } 35 public string LibrariesXMLFile { get; set; }
37 36
diff --git a/OpenSim/Framework/Configuration/HTTP/Properties/AssemblyInfo.cs b/OpenSim/Framework/Configuration/HTTP/Properties/AssemblyInfo.cs
index 3ef9682..05a2e0e 100644
--- a/OpenSim/Framework/Configuration/HTTP/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/Configuration/HTTP/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Framework/Configuration/XML/Properties/AssemblyInfo.cs b/OpenSim/Framework/Configuration/XML/Properties/AssemblyInfo.cs
index cbdffeb..d928a94 100644
--- a/OpenSim/Framework/Configuration/XML/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/Configuration/XML/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Framework/Configuration/XML/XmlConfiguration.cs b/OpenSim/Framework/Configuration/XML/XmlConfiguration.cs
index 43162fc..3152a7d 100644
--- a/OpenSim/Framework/Configuration/XML/XmlConfiguration.cs
+++ b/OpenSim/Framework/Configuration/XML/XmlConfiguration.cs
@@ -121,7 +121,7 @@ namespace OpenSim.Framework.Configuration.XML
121 121
122 public void Commit() 122 public void Commit()
123 { 123 {
124 if (fileName == null || fileName == String.Empty) 124 if (string.IsNullOrEmpty(fileName))
125 return; 125 return;
126 126
127 if (!Directory.Exists(Util.configDir())) 127 if (!Directory.Exists(Util.configDir()))
diff --git a/OpenSim/Framework/Console/AssemblyInfo.cs b/OpenSim/Framework/Console/AssemblyInfo.cs
index c618454..ba59025 100644
--- a/OpenSim/Framework/Console/AssemblyInfo.cs
+++ b/OpenSim/Framework/Console/AssemblyInfo.cs
@@ -55,4 +55,4 @@ using System.Runtime.InteropServices;
55// You can specify all values by your own or you can build default build and revision 55// You can specify all values by your own or you can build default build and revision
56// numbers with the '*' character (the default): 56// numbers with the '*' character (the default):
57 57
58[assembly : AssemblyVersion("0.7.6.*")] 58[assembly : AssemblyVersion("0.8.0.*")]
diff --git a/OpenSim/Framework/Console/ConsoleUtil.cs b/OpenSim/Framework/Console/ConsoleUtil.cs
index 97a86a8..794bfaf 100644
--- a/OpenSim/Framework/Console/ConsoleUtil.cs
+++ b/OpenSim/Framework/Console/ConsoleUtil.cs
@@ -156,12 +156,32 @@ namespace OpenSim.Framework.Console
156 } 156 }
157 157
158 /// <summary> 158 /// <summary>
159 /// Convert a minimum vector input from the console to an OpenMetaverse.Vector3 159 /// Convert a console integer to an int, automatically complaining if a console is given.
160 /// </summary> 160 /// </summary>
161 /// <param name='console'>Can be null if no console is available.</param> 161 /// <param name='console'>Can be null if no console is available.</param>
162 /// <param name='rawConsoleVector'>/param> 162 /// <param name='rawConsoleVector'>/param>
163 /// <param name='vector'></param> 163 /// <param name='vector'></param>
164 /// <returns></returns> 164 /// <returns></returns>
165 public static bool TryParseConsoleBool(ICommandConsole console, string rawConsoleString, out bool b)
166 {
167 if (!bool.TryParse(rawConsoleString, out b))
168 {
169 if (console != null)
170 console.OutputFormat("ERROR: {0} is not a true or false value", rawConsoleString);
171
172 return false;
173 }
174
175 return true;
176 }
177
178 /// <summary>
179 /// Convert a console integer to an int, automatically complaining if a console is given.
180 /// </summary>
181 /// <param name='console'>Can be null if no console is available.</param>
182 /// <param name='rawConsoleInt'>/param>
183 /// <param name='i'></param>
184 /// <returns></returns>
165 public static bool TryParseConsoleInt(ICommandConsole console, string rawConsoleInt, out int i) 185 public static bool TryParseConsoleInt(ICommandConsole console, string rawConsoleInt, out int i)
166 { 186 {
167 if (!int.TryParse(rawConsoleInt, out i)) 187 if (!int.TryParse(rawConsoleInt, out i))
@@ -174,6 +194,31 @@ namespace OpenSim.Framework.Console
174 194
175 return true; 195 return true;
176 } 196 }
197
198 /// <summary>
199 /// Convert a console integer to a natural int, automatically complaining if a console is given.
200 /// </summary>
201 /// <param name='console'>Can be null if no console is available.</param>
202 /// <param name='rawConsoleInt'>/param>
203 /// <param name='i'></param>
204 /// <returns></returns>
205 public static bool TryParseConsoleNaturalInt(ICommandConsole console, string rawConsoleInt, out int i)
206 {
207 if (TryParseConsoleInt(console, rawConsoleInt, out i))
208 {
209 if (i < 0)
210 {
211 if (console != null)
212 console.OutputFormat("ERROR: {0} is not a positive integer", rawConsoleInt);
213
214 return false;
215 }
216
217 return true;
218 }
219
220 return false;
221 }
177 222
178 /// <summary> 223 /// <summary>
179 /// Convert a minimum vector input from the console to an OpenMetaverse.Vector3 224 /// Convert a minimum vector input from the console to an OpenMetaverse.Vector3
diff --git a/OpenSim/Framework/Console/LocalConsole.cs b/OpenSim/Framework/Console/LocalConsole.cs
index d41481f..a967db6 100644
--- a/OpenSim/Framework/Console/LocalConsole.cs
+++ b/OpenSim/Framework/Console/LocalConsole.cs
@@ -426,6 +426,21 @@ namespace OpenSim.Framework.Console
426 System.Console.Write("{0}", prompt); 426 System.Console.Write("{0}", prompt);
427 427
428 break; 428 break;
429 case ConsoleKey.Delete:
430 if (m_cursorXPosition == m_commandLine.Length)
431 break;
432
433 m_commandLine.Remove(m_cursorXPosition, 1);
434
435 SetCursorLeft(0);
436 m_cursorYPosition = SetCursorTop(m_cursorYPosition);
437
438 if (m_echo)
439 System.Console.Write("{0}{1} ", prompt, m_commandLine);
440 else
441 System.Console.Write("{0}", prompt);
442
443 break;
429 case ConsoleKey.End: 444 case ConsoleKey.End:
430 m_cursorXPosition = m_commandLine.Length; 445 m_cursorXPosition = m_commandLine.Length;
431 break; 446 break;
diff --git a/OpenSim/Framework/Console/RemoteConsole.cs b/OpenSim/Framework/Console/RemoteConsole.cs
index 3e3c2b3..8ad7b0d 100644
--- a/OpenSim/Framework/Console/RemoteConsole.cs
+++ b/OpenSim/Framework/Console/RemoteConsole.cs
@@ -234,7 +234,7 @@ namespace OpenSim.Framework.Console
234 string uri = "/ReadResponses/" + sessionID.ToString() + "/"; 234 string uri = "/ReadResponses/" + sessionID.ToString() + "/";
235 235
236 m_Server.AddPollServiceHTTPHandler( 236 m_Server.AddPollServiceHTTPHandler(
237 uri, new PollServiceEventArgs(null, HasEvents, GetEvents, NoEvents, sessionID,25000)); // 25 secs timeout 237 uri, new PollServiceEventArgs(null, uri, HasEvents, GetEvents, NoEvents, sessionID,25000)); // 25 secs timeout
238 238
239 XmlDocument xmldoc = new XmlDocument(); 239 XmlDocument xmldoc = new XmlDocument();
240 XmlNode xmlnode = xmldoc.CreateNode(XmlNodeType.XmlDeclaration, 240 XmlNode xmlnode = xmldoc.CreateNode(XmlNodeType.XmlDeclaration,
diff --git a/OpenSim/Framework/Constants.cs b/OpenSim/Framework/Constants.cs
index a2eb5ee..3ba264c 100644
--- a/OpenSim/Framework/Constants.cs
+++ b/OpenSim/Framework/Constants.cs
@@ -30,9 +30,18 @@ namespace OpenSim.Framework
30{ 30{
31 public class Constants 31 public class Constants
32 { 32 {
33 // 'RegionSize' is the legacy region size.
34 // DO NOT USE THIS FOR ANY NEW CODE. Use Scene.RegionInfo.RegionSize[XYZ] as a region might not
35 // be the legacy region size.
33 public const uint RegionSize = 256; 36 public const uint RegionSize = 256;
34 public const uint RegionHeight = 4096; 37 public const uint RegionHeight = 4096;
35 public const byte TerrainPatchSize = 16; 38 // This could be a parameters but, really, a region of greater than this is pretty unmanageable
39 public const uint MaximumRegionSize = 8192;
40
41 // Since terrain is stored in 16x16 heights, regions must be a multiple of this number and that is the minimum
42 public const int MinRegionSize = 16;
43 public const int TerrainPatchSize = 16;
44
36 public const string DefaultTexture = "89556747-24cb-43ed-920b-47caed15465f"; 45 public const string DefaultTexture = "89556747-24cb-43ed-920b-47caed15465f";
37 46
38 public enum EstateAccessCodex : uint 47 public enum EstateAccessCodex : uint
diff --git a/OpenSim/Framework/DAMap.cs b/OpenSim/Framework/DAMap.cs
index df4a6bc..4995a92 100644
--- a/OpenSim/Framework/DAMap.cs
+++ b/OpenSim/Framework/DAMap.cs
@@ -29,10 +29,12 @@ using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.IO; 31using System.IO;
32using System.Reflection;
32using System.Text; 33using System.Text;
33using System.Xml; 34using System.Xml;
34using System.Xml.Schema; 35using System.Xml.Schema;
35using System.Xml.Serialization; 36using System.Xml.Serialization;
37using log4net;
36using OpenMetaverse; 38using OpenMetaverse;
37using OpenMetaverse.StructuredData; 39using OpenMetaverse.StructuredData;
38 40
@@ -48,13 +50,20 @@ namespace OpenSim.Framework
48 /// within their data store. However, avoid storing large amounts of data because that 50 /// within their data store. However, avoid storing large amounts of data because that
49 /// would slow down database access. 51 /// would slow down database access.
50 /// </remarks> 52 /// </remarks>
51 public class DAMap : IDictionary<string, OSDMap>, IXmlSerializable 53 public class DAMap : IXmlSerializable
52 { 54 {
53 private static readonly int MIN_STORE_NAME_LENGTH = 4; 55// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
54 56
55 protected OSDMap m_map; 57 private static readonly int MIN_NAMESPACE_LENGTH = 4;
56 58
57 public DAMap() { m_map = new OSDMap(); } 59 private OSDMap m_map = new OSDMap();
60
61 // WARNING: this is temporary for experimentation only, it will be removed!!!!
62 public OSDMap TopLevelMap
63 {
64 get { return m_map; }
65 set { m_map = value; }
66 }
58 67
59 public XmlSchema GetSchema() { return null; } 68 public XmlSchema GetSchema() { return null; }
60 69
@@ -64,39 +73,34 @@ namespace OpenSim.Framework
64 map.ReadXml(rawXml); 73 map.ReadXml(rawXml);
65 return map; 74 return map;
66 } 75 }
67 76
77 public void ReadXml(XmlReader reader)
78 {
79 ReadXml(reader.ReadInnerXml());
80 }
81
68 public void ReadXml(string rawXml) 82 public void ReadXml(string rawXml)
69 { 83 {
70 // System.Console.WriteLine("Trying to deserialize [{0}]", rawXml); 84 // System.Console.WriteLine("Trying to deserialize [{0}]", rawXml);
71 85
72 lock (this) 86 lock (this)
87 {
73 m_map = (OSDMap)OSDParser.DeserializeLLSDXml(rawXml); 88 m_map = (OSDMap)OSDParser.DeserializeLLSDXml(rawXml);
89 SanitiseMap(this);
90 }
74 } 91 }
75 92
76 // WARNING: this is temporary for experimentation only, it will be removed!!!! 93 public void WriteXml(XmlWriter writer)
77 public OSDMap TopLevelMap
78 { 94 {
79 get { return m_map; } 95 writer.WriteRaw(ToXml());
80 set { m_map = value; }
81 } 96 }
82
83 97
84 public void ReadXml(XmlReader reader)
85 {
86 ReadXml(reader.ReadInnerXml());
87 }
88
89 public string ToXml() 98 public string ToXml()
90 { 99 {
91 lock (this) 100 lock (this)
92 return OSDParser.SerializeLLSDXmlString(m_map); 101 return OSDParser.SerializeLLSDXmlString(m_map);
93 } 102 }
94 103
95 public void WriteXml(XmlWriter writer)
96 {
97 writer.WriteRaw(ToXml());
98 }
99
100 public void CopyFrom(DAMap other) 104 public void CopyFrom(DAMap other)
101 { 105 {
102 // Deep copy 106 // Deep copy
@@ -104,7 +108,7 @@ namespace OpenSim.Framework
104 string data = null; 108 string data = null;
105 lock (other) 109 lock (other)
106 { 110 {
107 if (other.Count > 0) 111 if (other.CountNamespaces > 0)
108 { 112 {
109 data = OSDParser.SerializeLLSDXmlString(other.m_map); 113 data = OSDParser.SerializeLLSDXmlString(other.m_map);
110 } 114 }
@@ -120,59 +124,132 @@ namespace OpenSim.Framework
120 } 124 }
121 125
122 /// <summary> 126 /// <summary>
123 /// Returns the number of data stores. 127 /// Sanitise the map to remove any namespaces or stores that are not OSDMap.
124 /// </summary> 128 /// </summary>
125 public int Count { get { lock (this) { return m_map.Count; } } } 129 /// <param name='map'>
126 130 /// </param>
127 public bool IsReadOnly { get { return false; } } 131 public static void SanitiseMap(DAMap daMap)
128 132 {
133 List<string> keysToRemove = null;
134
135 OSDMap namespacesMap = daMap.m_map;
136
137 foreach (string key in namespacesMap.Keys)
138 {
139// Console.WriteLine("Processing ns {0}", key);
140 if (!(namespacesMap[key] is OSDMap))
141 {
142 if (keysToRemove == null)
143 keysToRemove = new List<string>();
144
145 keysToRemove.Add(key);
146 }
147 }
148
149 if (keysToRemove != null)
150 {
151 foreach (string key in keysToRemove)
152 {
153// Console.WriteLine ("Removing bad ns {0}", key);
154 namespacesMap.Remove(key);
155 }
156 }
157
158 foreach (OSD nsOsd in namespacesMap.Values)
159 {
160 OSDMap nsOsdMap = (OSDMap)nsOsd;
161 keysToRemove = null;
162
163 foreach (string key in nsOsdMap.Keys)
164 {
165 if (!(nsOsdMap[key] is OSDMap))
166 {
167 if (keysToRemove == null)
168 keysToRemove = new List<string>();
169
170 keysToRemove.Add(key);
171 }
172 }
173
174 if (keysToRemove != null)
175 foreach (string key in keysToRemove)
176 nsOsdMap.Remove(key);
177 }
178 }
179
129 /// <summary> 180 /// <summary>
130 /// Returns the names of the data stores. 181 /// Get the number of namespaces
131 /// </summary> 182 /// </summary>
132 public ICollection<string> Keys { get { lock (this) { return m_map.Keys; } } } 183 public int CountNamespaces { get { lock (this) { return m_map.Count; } } }
133 184
134 /// <summary> 185 /// <summary>
135 /// Returns all the data stores. 186 /// Get the number of stores.
136 /// </summary> 187 /// </summary>
137 public ICollection<OSDMap> Values 188 public int CountStores
138 { 189 {
139 get 190 get
140 { 191 {
192 int count = 0;
193
141 lock (this) 194 lock (this)
142 { 195 {
143 List<OSDMap> stores = new List<OSDMap>(m_map.Count); 196 foreach (OSD osdNamespace in m_map)
144 foreach (OSD llsd in m_map.Values) 197 {
145 stores.Add((OSDMap)llsd); 198 count += ((OSDMap)osdNamespace).Count;
146 return stores; 199 }
147 } 200 }
201
202 return count;
148 } 203 }
149 } 204 }
150 205
151 /// <summary> 206 /// <summary>
152 /// Gets or sets one data store. 207 /// Retrieve a Dynamic Attribute store
153 /// </summary> 208 /// </summary>
154 /// <param name="key">Store name</param> 209 /// <param name="ns">namespace for the store - use "OpenSim" for in-core modules</param>
155 /// <returns></returns> 210 /// <param name="storeName">name of the store within the namespace</param>
156 public OSDMap this[string key] 211 /// <returns>an OSDMap representing the stored data, or null if not found</returns>
157 { 212 public OSDMap GetStore(string ns, string storeName)
158 get 213 {
159 { 214 OSD namespaceOsd;
160 OSD llsd; 215
161 216 lock (this)
162 lock (this) 217 {
218 if (m_map.TryGetValue(ns, out namespaceOsd))
163 { 219 {
164 if (m_map.TryGetValue(key, out llsd)) 220 OSD store;
165 return (OSDMap)llsd; 221
166 else 222 if (((OSDMap)namespaceOsd).TryGetValue(storeName, out store))
167 return null; 223 return (OSDMap)store;
168 } 224 }
169 } 225 }
170 226
171 set 227 return null;
228 }
229
230 /// <summary>
231 /// Saves a Dynamic attribute store
232 /// </summary>
233 /// <param name="ns">namespace for the store - use "OpenSim" for in-core modules</param>
234 /// <param name="storeName">name of the store within the namespace</param>
235 /// <param name="store">an OSDMap representing the data to store</param>
236 public void SetStore(string ns, string storeName, OSDMap store)
237 {
238 ValidateNamespace(ns);
239 OSDMap nsMap;
240
241 lock (this)
172 { 242 {
173 ValidateKey(key); 243 if (!m_map.ContainsKey(ns))
174 lock (this) 244 {
175 m_map[key] = value; 245 nsMap = new OSDMap();
246 m_map[ns] = nsMap;
247 }
248
249 nsMap = (OSDMap)m_map[ns];
250
251// m_log.DebugFormat("[DA MAP]: Setting store to {0}:{1}", ns, storeName);
252 nsMap[storeName] = store;
176 } 253 }
177 } 254 }
178 255
@@ -180,54 +257,46 @@ namespace OpenSim.Framework
180 /// Validate the key used for storing separate data stores. 257 /// Validate the key used for storing separate data stores.
181 /// </summary> 258 /// </summary>
182 /// <param name='key'></param> 259 /// <param name='key'></param>
183 public static void ValidateKey(string key) 260 public static void ValidateNamespace(string ns)
184 { 261 {
185 if (key.Length < MIN_STORE_NAME_LENGTH) 262 if (ns.Length < MIN_NAMESPACE_LENGTH)
186 throw new Exception("Minimum store name length is " + MIN_STORE_NAME_LENGTH); 263 throw new Exception("Minimum namespace length is " + MIN_NAMESPACE_LENGTH);
187 } 264 }
188 265
189 public bool ContainsKey(string key) 266 public bool ContainsStore(string ns, string storeName)
190 { 267 {
191 lock (this) 268 OSD namespaceOsd;
192 return m_map.ContainsKey(key);
193 }
194 269
195 public void Add(string key, OSDMap store)
196 {
197 ValidateKey(key);
198 lock (this)
199 m_map.Add(key, store);
200 }
201
202 public void Add(KeyValuePair<string, OSDMap> kvp)
203 {
204 ValidateKey(kvp.Key);
205 lock (this) 270 lock (this)
206 m_map.Add(kvp.Key, kvp.Value); 271 {
207 } 272 if (m_map.TryGetValue(ns, out namespaceOsd))
273 {
274 return ((OSDMap)namespaceOsd).ContainsKey(storeName);
275 }
276 }
208 277
209 public bool Remove(string key) 278 return false;
210 { 279 }
211 lock (this)
212 return m_map.Remove(key);
213 }
214 280
215 public bool TryGetValue(string key, out OSDMap store) 281 public bool TryGetStore(string ns, string storeName, out OSDMap store)
216 { 282 {
283 OSD namespaceOsd;
284
217 lock (this) 285 lock (this)
218 { 286 {
219 OSD llsd; 287 if (m_map.TryGetValue(ns, out namespaceOsd))
220 if (m_map.TryGetValue(key, out llsd))
221 {
222 store = (OSDMap)llsd;
223 return true;
224 }
225 else
226 { 288 {
227 store = null; 289 OSD storeOsd;
228 return false; 290
291 bool result = ((OSDMap)namespaceOsd).TryGetValue(storeName, out storeOsd);
292 store = (OSDMap)storeOsd;
293
294 return result;
229 } 295 }
230 } 296 }
297
298 store = null;
299 return false;
231 } 300 }
232 301
233 public void Clear() 302 public void Clear()
@@ -235,39 +304,25 @@ namespace OpenSim.Framework
235 lock (this) 304 lock (this)
236 m_map.Clear(); 305 m_map.Clear();
237 } 306 }
238
239 public bool Contains(KeyValuePair<string, OSDMap> kvp)
240 {
241 lock (this)
242 return m_map.ContainsKey(kvp.Key);
243 }
244
245 public void CopyTo(KeyValuePair<string, OSDMap>[] array, int index)
246 {
247 throw new NotImplementedException();
248 }
249 307
250 public bool Remove(KeyValuePair<string, OSDMap> kvp) 308 public bool RemoveStore(string ns, string storeName)
251 { 309 {
252 lock (this) 310 OSD namespaceOsd;
253 return m_map.Remove(kvp.Key);
254 }
255 311
256 public System.Collections.IDictionaryEnumerator GetEnumerator()
257 {
258 lock (this) 312 lock (this)
259 return m_map.GetEnumerator(); 313 {
260 } 314 if (m_map.TryGetValue(ns, out namespaceOsd))
315 {
316 OSDMap namespaceOsdMap = (OSDMap)namespaceOsd;
317 namespaceOsdMap.Remove(storeName);
261 318
262 IEnumerator<KeyValuePair<string, OSDMap>> IEnumerable<KeyValuePair<string, OSDMap>>.GetEnumerator() 319 // Don't keep empty namespaces around
263 { 320 if (namespaceOsdMap.Count <= 0)
264 return null; 321 m_map.Remove(ns);
265 } 322 }
323 }
266 324
267 IEnumerator IEnumerable.GetEnumerator() 325 return false;
268 { 326 }
269 lock (this)
270 return m_map.GetEnumerator();
271 }
272 } 327 }
273} \ No newline at end of file 328} \ No newline at end of file
diff --git a/OpenSim/Framework/DOMap.cs b/OpenSim/Framework/DOMap.cs
index 755e129..f5b650b 100644
--- a/OpenSim/Framework/DOMap.cs
+++ b/OpenSim/Framework/DOMap.cs
@@ -42,22 +42,22 @@ namespace OpenSim.Framework
42 /// This class stores and retrieves dynamic objects. 42 /// This class stores and retrieves dynamic objects.
43 /// </summary> 43 /// </summary>
44 /// <remarks> 44 /// <remarks>
45 /// Experimental - DO NOT USE. 45 /// Experimental - DO NOT USE. Does not yet have namespace support.
46 /// </remarks> 46 /// </remarks>
47 public class DOMap 47 public class DOMap
48 { 48 {
49 private IDictionary<string, object> m_map; 49 private IDictionary<string, object> m_map;
50 50
51 public void Add(string key, object dynObj) 51 public void Add(string ns, string objName, object dynObj)
52 { 52 {
53 DAMap.ValidateKey(key); 53 DAMap.ValidateNamespace(ns);
54 54
55 lock (this) 55 lock (this)
56 { 56 {
57 if (m_map == null) 57 if (m_map == null)
58 m_map = new Dictionary<string, object>(); 58 m_map = new Dictionary<string, object>();
59 59
60 m_map.Add(key, dynObj); 60 m_map.Add(objName, dynObj);
61 } 61 }
62 } 62 }
63 63
diff --git a/OpenSim/Framework/EstateSettings.cs b/OpenSim/Framework/EstateSettings.cs
index e03750b..5ddbd61 100644
--- a/OpenSim/Framework/EstateSettings.cs
+++ b/OpenSim/Framework/EstateSettings.cs
@@ -430,6 +430,5 @@ namespace OpenSim.Framework
430 { 430 {
431 return l_EstateGroups.Contains(groupID); 431 return l_EstateGroups.Contains(groupID);
432 } 432 }
433
434 } 433 }
435} 434}
diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs
index ad3471a..22cc79d 100644
--- a/OpenSim/Framework/IClientAPI.cs
+++ b/OpenSim/Framework/IClientAPI.cs
@@ -65,6 +65,7 @@ namespace OpenSim.Framework
65 public delegate void NetworkStats(int inPackets, int outPackets, int unAckedBytes); 65 public delegate void NetworkStats(int inPackets, int outPackets, int unAckedBytes);
66 66
67 public delegate void SetAppearance(IClientAPI remoteClient, Primitive.TextureEntry textureEntry, byte[] visualParams, Vector3 AvSize, WearableCacheItem[] CacheItems); 67 public delegate void SetAppearance(IClientAPI remoteClient, Primitive.TextureEntry textureEntry, byte[] visualParams, Vector3 AvSize, WearableCacheItem[] CacheItems);
68 public delegate void CachedTextureRequest(IClientAPI remoteClient, int serial, List<CachedTextureRequestArg> cachedTextureRequest);
68 69
69 public delegate void StartAnim(IClientAPI remoteClient, UUID animID); 70 public delegate void StartAnim(IClientAPI remoteClient, UUID animID);
70 71
@@ -789,6 +790,7 @@ namespace OpenSim.Framework
789 event EstateChangeInfo OnEstateChangeInfo; 790 event EstateChangeInfo OnEstateChangeInfo;
790 event EstateManageTelehub OnEstateManageTelehub; 791 event EstateManageTelehub OnEstateManageTelehub;
791 // [Obsolete("LLClientView Specific.")] 792 // [Obsolete("LLClientView Specific.")]
793 event CachedTextureRequest OnCachedTextureRequest;
792 event SetAppearance OnSetAppearance; 794 event SetAppearance OnSetAppearance;
793 // [Obsolete("LLClientView Specific - Replace and rename OnAvatarUpdate. Difference from SetAppearance?")] 795 // [Obsolete("LLClientView Specific - Replace and rename OnAvatarUpdate. Difference from SetAppearance?")]
794 event AvatarNowWearing OnAvatarNowWearing; 796 event AvatarNowWearing OnAvatarNowWearing;
@@ -832,6 +834,8 @@ namespace OpenSim.Framework
832 /// </remarks> 834 /// </remarks>
833 event UpdateAgent OnAgentUpdate; 835 event UpdateAgent OnAgentUpdate;
834 836
837 event UpdateAgent OnAgentCameraUpdate;
838
835 event AgentRequestSit OnAgentRequestSit; 839 event AgentRequestSit OnAgentRequestSit;
836 event AgentSit OnAgentSit; 840 event AgentSit OnAgentSit;
837 event AvatarPickerRequest OnAvatarPickerRequest; 841 event AvatarPickerRequest OnAvatarPickerRequest;
@@ -1100,14 +1104,15 @@ namespace OpenSim.Framework
1100 /// <param name="textureEntry"></param> 1104 /// <param name="textureEntry"></param>
1101 void SendAppearance(UUID agentID, byte[] visualParams, byte[] textureEntry); 1105 void SendAppearance(UUID agentID, byte[] visualParams, byte[] textureEntry);
1102 1106
1107 void SendCachedTextureResponse(ISceneEntity avatar, int serial, List<CachedTextureResponseArg> cachedTextures);
1108
1103 void SendStartPingCheck(byte seq); 1109 void SendStartPingCheck(byte seq);
1104 1110
1105 /// <summary> 1111 /// <summary>
1106 /// Tell the client that an object has been deleted 1112 /// Tell the client that an object has been deleted
1107 /// </summary> 1113 /// </summary>
1108 /// <param name="regionHandle"></param>
1109 /// <param name="localID"></param> 1114 /// <param name="localID"></param>
1110 void SendKillObject(ulong regionHandle, List<uint> localID); 1115 void SendKillObject(List<uint> localID);
1111 1116
1112 void SendAnimations(UUID[] animID, int[] seqs, UUID sourceAgentId, UUID[] objectIDs); 1117 void SendAnimations(UUID[] animID, int[] seqs, UUID sourceAgentId, UUID[] objectIDs);
1113 void SendRegionHandshake(RegionInfo regionInfo, RegionHandshakeArgs args); 1118 void SendRegionHandshake(RegionInfo regionInfo, RegionHandshakeArgs args);
@@ -1486,7 +1491,7 @@ namespace OpenSim.Framework
1486 void SendChangeUserRights(UUID agentID, UUID friendID, int rights); 1491 void SendChangeUserRights(UUID agentID, UUID friendID, int rights);
1487 void SendTextBoxRequest(string message, int chatChannel, string objectname, UUID ownerID, string ownerFirstName, string ownerLastName, UUID objectId); 1492 void SendTextBoxRequest(string message, int chatChannel, string objectname, UUID ownerID, string ownerFirstName, string ownerLastName, UUID objectId);
1488 1493
1489 void StopFlying(ISceneEntity presence); 1494 void SendAgentTerseUpdate(ISceneEntity presence);
1490 1495
1491 void SendPlacesReply(UUID queryID, UUID transactionID, PlacesReplyData[] data); 1496 void SendPlacesReply(UUID queryID, UUID transactionID, PlacesReplyData[] data);
1492 } 1497 }
diff --git a/OpenSim/Framework/IImprovedAssetCache.cs b/OpenSim/Framework/IImprovedAssetCache.cs
index a0b8b55..a853e90 100644
--- a/OpenSim/Framework/IImprovedAssetCache.cs
+++ b/OpenSim/Framework/IImprovedAssetCache.cs
@@ -31,10 +31,34 @@ namespace OpenSim.Framework
31{ 31{
32 public interface IImprovedAssetCache 32 public interface IImprovedAssetCache
33 { 33 {
34 /// <summary>
35 /// Cache the specified asset.
36 /// </summary>
37 /// <param name='asset'></param>
34 void Cache(AssetBase asset); 38 void Cache(AssetBase asset);
39
40 /// <summary>
41 /// Get an asset by its id.
42 /// </summary>
43 /// <param name='id'></param>
44 /// <returns>null if the asset does not exist.</returns>
35 AssetBase Get(string id); 45 AssetBase Get(string id);
46
47 /// <summary>
48 /// Check whether an asset with the specified id exists in the cache.
49 /// </summary>
50 /// <param name='id'></param>
36 bool Check(string id); 51 bool Check(string id);
52
53 /// <summary>
54 /// Expire an asset from the cache.
55 /// </summary>
56 /// <param name='id'></param>
37 void Expire(string id); 57 void Expire(string id);
58
59 /// <summary>
60 /// Clear the cache.
61 /// </summary>
38 void Clear(); 62 void Clear();
39 } 63 }
40} 64} \ No newline at end of file
diff --git a/OpenSim/Framework/IPeople.cs b/OpenSim/Framework/IPeople.cs
new file mode 100644
index 0000000..b88e103
--- /dev/null
+++ b/OpenSim/Framework/IPeople.cs
@@ -0,0 +1,47 @@
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 OpenMetaverse;
31
32namespace OpenSim.Framework
33{
34 public class UserData
35 {
36 public UUID Id { get; set; }
37 public string FirstName { get; set; }
38 public string LastName { get; set; }
39 public string HomeURL { get; set; }
40 public Dictionary<string, object> ServerURLs { get; set; }
41 }
42
43 public interface IPeople
44 {
45 List<UserData> GetUserData(string query, int page_size, int page_number);
46 }
47} \ No newline at end of file
diff --git a/OpenSim/Framework/IScene.cs b/OpenSim/Framework/IScene.cs
index 87ec99e..e1b6d1e 100644
--- a/OpenSim/Framework/IScene.cs
+++ b/OpenSim/Framework/IScene.cs
@@ -86,24 +86,26 @@ namespace OpenSim.Framework
86 event restart OnRestart; 86 event restart OnRestart;
87 87
88 /// <summary> 88 /// <summary>
89 /// Add a new client and create a presence for it. All clients except initial login clients will starts off as a child agent 89 /// Add a new agent with an attached client. All agents except initial login clients will starts off as a child agent
90 /// - the later agent crossing will promote it to a root agent. 90 /// - the later agent crossing will promote it to a root agent.
91 /// </summary> 91 /// </summary>
92 /// <param name="client"></param> 92 /// <param name="client"></param>
93 /// <param name="type">The type of agent to add.</param> 93 /// <param name="type">The type of agent to add.</param>
94 /// <returns> 94 /// <returns>
95 /// The scene agent if the new client was added or if an agent that already existed.</returns> 95 /// The scene agent if the new client was added or if an agent that already existed.</returns>
96 ISceneAgent AddNewClient(IClientAPI client, PresenceType type); 96 ISceneAgent AddNewAgent(IClientAPI client, PresenceType type);
97 97
98 /// <summary> 98 /// <summary>
99 /// Remove the given client from the scene. 99 /// Tell a single agent to disconnect from the region.
100 /// </summary> 100 /// </summary>
101 /// <param name="agentID"></param> 101 /// <param name="agentID"></param>
102 /// <param name="closeChildAgents">Close the neighbour child agents associated with this client.</param> 102 /// <param name="force">
103 void RemoveClient(UUID agentID, bool closeChildAgents); 103 /// Force the agent to close even if it might be in the middle of some other operation. You do not want to
104 /// force unless you are absolutely sure that the agent is dead and a normal close is not working.
105 /// </param>
106 bool CloseAgent(UUID agentID, bool force);
104 107
105 void Restart(); 108 void Restart();
106 //RegionInfo OtherRegionUp(RegionInfo thisRegion);
107 109
108 string GetSimulatorVersion(); 110 string GetSimulatorVersion();
109 111
@@ -136,5 +138,10 @@ namespace OpenSim.Framework
136 ISceneObject DeserializeObject(string representation); 138 ISceneObject DeserializeObject(string representation);
137 139
138 bool CheckClient(UUID agentID, System.Net.IPEndPoint ep); 140 bool CheckClient(UUID agentID, System.Net.IPEndPoint ep);
141
142 /// <summary>
143 /// Start the scene and associated scripts within it.
144 /// </summary>
145 void Start();
139 } 146 }
140} 147} \ No newline at end of file
diff --git a/OpenSim/Framework/InventoryItemBase.cs b/OpenSim/Framework/InventoryItemBase.cs
index 3d45e76..558dfd0 100644
--- a/OpenSim/Framework/InventoryItemBase.cs
+++ b/OpenSim/Framework/InventoryItemBase.cs
@@ -122,7 +122,7 @@ namespace OpenSim.Framework
122 { 122 {
123 get 123 get
124 { 124 {
125 if (m_creatorData != null && m_creatorData != string.Empty) 125 if (!string.IsNullOrEmpty(m_creatorData))
126 return m_creatorId + ';' + m_creatorData; 126 return m_creatorId + ';' + m_creatorData;
127 else 127 else
128 return m_creatorId; 128 return m_creatorId;
diff --git a/OpenSim/Framework/Location.cs b/OpenSim/Framework/Location.cs
index 9504e03..0b88834 100644
--- a/OpenSim/Framework/Location.cs
+++ b/OpenSim/Framework/Location.cs
@@ -33,10 +33,10 @@ namespace OpenSim.Framework
33 [Serializable] 33 [Serializable]
34 public class Location : ICloneable 34 public class Location : ICloneable
35 { 35 {
36 private readonly int m_x; 36 private readonly uint m_x;
37 private readonly int m_y; 37 private readonly uint m_y;
38 38
39 public Location(int x, int y) 39 public Location(uint x, uint y)
40 { 40 {
41 m_x = x; 41 m_x = x;
42 m_y = y; 42 m_y = y;
@@ -44,21 +44,21 @@ namespace OpenSim.Framework
44 44
45 public Location(ulong regionHandle) 45 public Location(ulong regionHandle)
46 { 46 {
47 m_x = (int) regionHandle; 47 m_x = (uint)(regionHandle >> 32);
48 m_y = (int) (regionHandle >> 32); 48 m_y = (uint)(regionHandle & (ulong)uint.MaxValue);
49 } 49 }
50 50
51 public ulong RegionHandle 51 public ulong RegionHandle
52 { 52 {
53 get { return Utils.UIntsToLong((uint)m_x, (uint)m_y); } 53 get { return Utils.UIntsToLong(m_x, m_y); }
54 } 54 }
55 55
56 public int X 56 public uint X
57 { 57 {
58 get { return m_x; } 58 get { return m_x; }
59 } 59 }
60 60
61 public int Y 61 public uint Y
62 { 62 {
63 get { return m_y; } 63 get { return m_y; }
64 } 64 }
diff --git a/OpenSim/Framework/Monitoring/BaseStatsCollector.cs b/OpenSim/Framework/Monitoring/BaseStatsCollector.cs
index 23dba09..96536e8 100644
--- a/OpenSim/Framework/Monitoring/BaseStatsCollector.cs
+++ b/OpenSim/Framework/Monitoring/BaseStatsCollector.cs
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
@@ -44,16 +44,16 @@ namespace OpenSim.Framework.Monitoring
44 sb.Append("MEMORY STATISTICS"); 44 sb.Append("MEMORY STATISTICS");
45 sb.Append(Environment.NewLine); 45 sb.Append(Environment.NewLine);
46 sb.AppendFormat( 46 sb.AppendFormat(
47 "Allocated to OpenSim objects: {0} MB\n", 47 "Heap allocated to OpenSim : {0} MB\n",
48 Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0)); 48 Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0));
49 49
50 sb.AppendFormat( 50 sb.AppendFormat(
51 "OpenSim last object memory churn : {0} MB/s\n", 51 "Last heap allocation rate : {0} MB/s\n",
52 Math.Round((MemoryWatchdog.LastMemoryChurn * 1000) / 1024.0 / 1024, 3)); 52 Math.Round((MemoryWatchdog.LastHeapAllocationRate * 1000) / 1024.0 / 1024, 3));
53 53
54 sb.AppendFormat( 54 sb.AppendFormat(
55 "OpenSim average object memory churn : {0} MB/s\n", 55 "Average heap allocation rate: {0} MB/s\n",
56 Math.Round((MemoryWatchdog.AverageMemoryChurn * 1000) / 1024.0 / 1024, 3)); 56 Math.Round((MemoryWatchdog.AverageHeapAllocationRate * 1000) / 1024.0 / 1024, 3));
57 57
58 Process myprocess = Process.GetCurrentProcess(); 58 Process myprocess = Process.GetCurrentProcess();
59 if (!myprocess.HasExited) 59 if (!myprocess.HasExited)
diff --git a/OpenSim/Framework/Monitoring/Checks/Check.cs b/OpenSim/Framework/Monitoring/Checks/Check.cs
new file mode 100644
index 0000000..594386a
--- /dev/null
+++ b/OpenSim/Framework/Monitoring/Checks/Check.cs
@@ -0,0 +1,118 @@
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.Text;
30
31namespace OpenSim.Framework.Monitoring
32{
33 public class Check
34 {
35// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
36
37 public static readonly char[] DisallowedShortNameCharacters = { '.' };
38
39 /// <summary>
40 /// Category of this stat (e.g. cache, scene, etc).
41 /// </summary>
42 public string Category { get; private set; }
43
44 /// <summary>
45 /// Containing name for this stat.
46 /// FIXME: In the case of a scene, this is currently the scene name (though this leaves
47 /// us with a to-be-resolved problem of non-unique region names).
48 /// </summary>
49 /// <value>
50 /// The container.
51 /// </value>
52 public string Container { get; private set; }
53
54 /// <summary>
55 /// Action used to check whether alert should go off.
56 /// </summary>
57 /// <remarks>
58 /// Should return true if check passes. False otherwise.
59 /// </remarks>
60 public Func<Check, bool> CheckFunc { get; private set; }
61
62 /// <summary>
63 /// Message from the last failure, if any. If there is no message or no failure then will be null.
64 /// </summary>
65 /// <remarks>
66 /// Should be set by the CheckFunc when applicable.
67 /// </remarks>
68 public string LastFailureMessage { get; set; }
69
70 public StatVerbosity Verbosity { get; private set; }
71 public string ShortName { get; private set; }
72 public string Name { get; private set; }
73 public string Description { get; private set; }
74
75 public Check(
76 string shortName,
77 string name,
78 string description,
79 string category,
80 string container,
81 Func<Check, bool> checkFunc,
82 StatVerbosity verbosity)
83 {
84 if (ChecksManager.SubCommands.Contains(category))
85 throw new Exception(
86 string.Format("Alert cannot be in category '{0}' since this is reserved for a subcommand", category));
87
88 foreach (char c in DisallowedShortNameCharacters)
89 {
90 if (shortName.IndexOf(c) != -1)
91 throw new Exception(string.Format("Alert name {0} cannot contain character {1}", shortName, c));
92 }
93
94 ShortName = shortName;
95 Name = name;
96 Description = description;
97 Category = category;
98 Container = container;
99 CheckFunc = checkFunc;
100 Verbosity = verbosity;
101 }
102
103 public bool CheckIt()
104 {
105 return CheckFunc(this);
106 }
107
108 public virtual string ToConsoleString()
109 {
110 return string.Format(
111 "{0}.{1}.{2} - {3}",
112 Category,
113 Container,
114 ShortName,
115 Description);
116 }
117 }
118} \ No newline at end of file
diff --git a/OpenSim/Framework/Monitoring/ChecksManager.cs b/OpenSim/Framework/Monitoring/ChecksManager.cs
new file mode 100644
index 0000000..e4a7f8c
--- /dev/null
+++ b/OpenSim/Framework/Monitoring/ChecksManager.cs
@@ -0,0 +1,262 @@
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.Reflection;
32using System.Text;
33using log4net;
34
35namespace OpenSim.Framework.Monitoring
36{
37 /// <summary>
38 /// Static class used to register/deregister checks on runtime conditions.
39 /// </summary>
40 public static class ChecksManager
41 {
42 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
43
44 // Subcommand used to list other stats.
45 public const string ListSubCommand = "list";
46
47 // All subcommands
48 public static HashSet<string> SubCommands = new HashSet<string> { ListSubCommand };
49
50 /// <summary>
51 /// Checks categorized by category/container/shortname
52 /// </summary>
53 /// <remarks>
54 /// Do not add or remove directly from this dictionary.
55 /// </remarks>
56 public static SortedDictionary<string, SortedDictionary<string, SortedDictionary<string, Check>>> RegisteredChecks
57 = new SortedDictionary<string, SortedDictionary<string, SortedDictionary<string, Check>>>();
58
59 public static void RegisterConsoleCommands(ICommandConsole console)
60 {
61 console.Commands.AddCommand(
62 "General",
63 false,
64 "show checks",
65 "show checks",
66 "Show checks configured for this server",
67 "If no argument is specified then info on all checks will be shown.\n"
68 + "'list' argument will show check categories.\n"
69 + "THIS FACILITY IS EXPERIMENTAL",
70 HandleShowchecksCommand);
71 }
72
73 public static void HandleShowchecksCommand(string module, string[] cmd)
74 {
75 ICommandConsole con = MainConsole.Instance;
76
77 if (cmd.Length > 2)
78 {
79 foreach (string name in cmd.Skip(2))
80 {
81 string[] components = name.Split('.');
82
83 string categoryName = components[0];
84// string containerName = components.Length > 1 ? components[1] : null;
85
86 if (categoryName == ListSubCommand)
87 {
88 con.Output("check categories available are:");
89
90 foreach (string category in RegisteredChecks.Keys)
91 con.OutputFormat(" {0}", category);
92 }
93// else
94// {
95// SortedDictionary<string, SortedDictionary<string, Check>> category;
96// if (!Registeredchecks.TryGetValue(categoryName, out category))
97// {
98// con.OutputFormat("No such category as {0}", categoryName);
99// }
100// else
101// {
102// if (String.IsNullOrEmpty(containerName))
103// {
104// OutputConfiguredToConsole(con, category);
105// }
106// else
107// {
108// SortedDictionary<string, Check> container;
109// if (category.TryGetValue(containerName, out container))
110// {
111// OutputContainerChecksToConsole(con, container);
112// }
113// else
114// {
115// con.OutputFormat("No such container {0} in category {1}", containerName, categoryName);
116// }
117// }
118// }
119// }
120 }
121 }
122 else
123 {
124 OutputAllChecksToConsole(con);
125 }
126 }
127
128 /// <summary>
129 /// Registers a statistic.
130 /// </summary>
131 /// <param name='stat'></param>
132 /// <returns></returns>
133 public static bool RegisterCheck(Check check)
134 {
135 SortedDictionary<string, SortedDictionary<string, Check>> category = null, newCategory;
136 SortedDictionary<string, Check> container = null, newContainer;
137
138 lock (RegisteredChecks)
139 {
140 // Check name is not unique across category/container/shortname key.
141 // XXX: For now just return false. This is to avoid problems in regression tests where all tests
142 // in a class are run in the same instance of the VM.
143 if (TryGetCheckParents(check, out category, out container))
144 return false;
145
146 // We take a copy-on-write approach here of replacing dictionaries when keys are added or removed.
147 // This means that we don't need to lock or copy them on iteration, which will be a much more
148 // common operation after startup.
149 if (container != null)
150 newContainer = new SortedDictionary<string, Check>(container);
151 else
152 newContainer = new SortedDictionary<string, Check>();
153
154 if (category != null)
155 newCategory = new SortedDictionary<string, SortedDictionary<string, Check>>(category);
156 else
157 newCategory = new SortedDictionary<string, SortedDictionary<string, Check>>();
158
159 newContainer[check.ShortName] = check;
160 newCategory[check.Container] = newContainer;
161 RegisteredChecks[check.Category] = newCategory;
162 }
163
164 return true;
165 }
166
167 /// <summary>
168 /// Deregister an check
169 /// </summary>>
170 /// <param name='stat'></param>
171 /// <returns></returns>
172 public static bool DeregisterCheck(Check check)
173 {
174 SortedDictionary<string, SortedDictionary<string, Check>> category = null, newCategory;
175 SortedDictionary<string, Check> container = null, newContainer;
176
177 lock (RegisteredChecks)
178 {
179 if (!TryGetCheckParents(check, out category, out container))
180 return false;
181
182 newContainer = new SortedDictionary<string, Check>(container);
183 newContainer.Remove(check.ShortName);
184
185 newCategory = new SortedDictionary<string, SortedDictionary<string, Check>>(category);
186 newCategory.Remove(check.Container);
187
188 newCategory[check.Container] = newContainer;
189 RegisteredChecks[check.Category] = newCategory;
190
191 return true;
192 }
193 }
194
195 public static bool TryGetCheckParents(
196 Check check,
197 out SortedDictionary<string, SortedDictionary<string, Check>> category,
198 out SortedDictionary<string, Check> container)
199 {
200 category = null;
201 container = null;
202
203 lock (RegisteredChecks)
204 {
205 if (RegisteredChecks.TryGetValue(check.Category, out category))
206 {
207 if (category.TryGetValue(check.Container, out container))
208 {
209 if (container.ContainsKey(check.ShortName))
210 return true;
211 }
212 }
213 }
214
215 return false;
216 }
217
218 public static void CheckChecks()
219 {
220 lock (RegisteredChecks)
221 {
222 foreach (SortedDictionary<string, SortedDictionary<string, Check>> category in RegisteredChecks.Values)
223 {
224 foreach (SortedDictionary<string, Check> container in category.Values)
225 {
226 foreach (Check check in container.Values)
227 {
228 if (!check.CheckIt())
229 m_log.WarnFormat(
230 "[CHECKS MANAGER]: Check {0}.{1}.{2} failed with message {3}", check.Category, check.Container, check.ShortName, check.LastFailureMessage);
231 }
232 }
233 }
234 }
235 }
236
237 private static void OutputAllChecksToConsole(ICommandConsole con)
238 {
239 foreach (var category in RegisteredChecks.Values)
240 {
241 OutputCategoryChecksToConsole(con, category);
242 }
243 }
244
245 private static void OutputCategoryChecksToConsole(
246 ICommandConsole con, SortedDictionary<string, SortedDictionary<string, Check>> category)
247 {
248 foreach (var container in category.Values)
249 {
250 OutputContainerChecksToConsole(con, container);
251 }
252 }
253
254 private static void OutputContainerChecksToConsole(ICommandConsole con, SortedDictionary<string, Check> container)
255 {
256 foreach (Check check in container.Values)
257 {
258 con.Output(check.ToConsoleString());
259 }
260 }
261 }
262} \ No newline at end of file
diff --git a/OpenSim/Framework/Monitoring/MemoryWatchdog.cs b/OpenSim/Framework/Monitoring/MemoryWatchdog.cs
index c6010cd..c474622 100644
--- a/OpenSim/Framework/Monitoring/MemoryWatchdog.cs
+++ b/OpenSim/Framework/Monitoring/MemoryWatchdog.cs
@@ -60,17 +60,17 @@ namespace OpenSim.Framework.Monitoring
60 private static bool m_enabled; 60 private static bool m_enabled;
61 61
62 /// <summary> 62 /// <summary>
63 /// Last memory churn in bytes per millisecond. 63 /// Average heap allocation rate in bytes per millisecond.
64 /// </summary> 64 /// </summary>
65 public static double AverageMemoryChurn 65 public static double AverageHeapAllocationRate
66 { 66 {
67 get { if (m_samples.Count > 0) return m_samples.Average(); else return 0; } 67 get { if (m_samples.Count > 0) return m_samples.Average(); else return 0; }
68 } 68 }
69 69
70 /// <summary> 70 /// <summary>
71 /// Average memory churn in bytes per millisecond. 71 /// Last heap allocation in bytes
72 /// </summary> 72 /// </summary>
73 public static double LastMemoryChurn 73 public static double LastHeapAllocationRate
74 { 74 {
75 get { if (m_samples.Count > 0) return m_samples.Last(); else return 0; } 75 get { if (m_samples.Count > 0) return m_samples.Last(); else return 0; }
76 } 76 }
diff --git a/OpenSim/Framework/Monitoring/Properties/AssemblyInfo.cs b/OpenSim/Framework/Monitoring/Properties/AssemblyInfo.cs
index 36678bb..07971bf 100644
--- a/OpenSim/Framework/Monitoring/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/Monitoring/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Framework/Monitoring/ServerStatsCollector.cs b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs
new file mode 100644
index 0000000..ac0f0bc
--- /dev/null
+++ b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs
@@ -0,0 +1,349 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Diagnostics;
31using System.Linq;
32using System.Net.NetworkInformation;
33using System.Text;
34using System.Threading;
35using log4net;
36using Nini.Config;
37using OpenMetaverse.StructuredData;
38using OpenSim.Framework;
39
40namespace OpenSim.Framework.Monitoring
41{
42 public class ServerStatsCollector
43 {
44 private readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
45 private readonly string LogHeader = "[SERVER STATS]";
46
47 public bool Enabled = false;
48 private static Dictionary<string, Stat> RegisteredStats = new Dictionary<string, Stat>();
49
50 public readonly string CategoryServer = "server";
51
52 public readonly string ContainerThreadpool = "threadpool";
53 public readonly string ContainerProcessor = "processor";
54 public readonly string ContainerMemory = "memory";
55 public readonly string ContainerNetwork = "network";
56 public readonly string ContainerProcess = "process";
57
58 public string NetworkInterfaceTypes = "Ethernet";
59
60 readonly int performanceCounterSampleInterval = 500;
61// int lastperformanceCounterSampleTime = 0;
62
63 private class PerfCounterControl
64 {
65 public PerformanceCounter perfCounter;
66 public int lastFetch;
67 public string name;
68 public PerfCounterControl(PerformanceCounter pPc)
69 : this(pPc, String.Empty)
70 {
71 }
72 public PerfCounterControl(PerformanceCounter pPc, string pName)
73 {
74 perfCounter = pPc;
75 lastFetch = 0;
76 name = pName;
77 }
78 }
79
80 PerfCounterControl processorPercentPerfCounter = null;
81
82 // IRegionModuleBase.Initialize
83 public void Initialise(IConfigSource source)
84 {
85 IConfig cfg = source.Configs["Monitoring"];
86
87 if (cfg != null)
88 Enabled = cfg.GetBoolean("ServerStatsEnabled", true);
89
90 if (Enabled)
91 {
92 NetworkInterfaceTypes = cfg.GetString("NetworkInterfaceTypes", "Ethernet");
93 }
94 }
95
96 public void Start()
97 {
98 if (RegisteredStats.Count == 0)
99 RegisterServerStats();
100 }
101
102 public void Close()
103 {
104 if (RegisteredStats.Count > 0)
105 {
106 foreach (Stat stat in RegisteredStats.Values)
107 {
108 StatsManager.DeregisterStat(stat);
109 stat.Dispose();
110 }
111 RegisteredStats.Clear();
112 }
113 }
114
115 private void MakeStat(string pName, string pDesc, string pUnit, string pContainer, Action<Stat> act)
116 {
117 MakeStat(pName, pDesc, pUnit, pContainer, act, MeasuresOfInterest.None);
118 }
119
120 private void MakeStat(string pName, string pDesc, string pUnit, string pContainer, Action<Stat> act, MeasuresOfInterest moi)
121 {
122 string desc = pDesc;
123 if (desc == null)
124 desc = pName;
125 Stat stat = new Stat(pName, pName, desc, pUnit, CategoryServer, pContainer, StatType.Pull, moi, act, StatVerbosity.Debug);
126 StatsManager.RegisterStat(stat);
127 RegisteredStats.Add(pName, stat);
128 }
129
130 public void RegisterServerStats()
131 {
132// lastperformanceCounterSampleTime = Util.EnvironmentTickCount();
133 PerformanceCounter tempPC;
134 Stat tempStat;
135 string tempName;
136
137 try
138 {
139 tempName = "CPUPercent";
140 tempPC = new PerformanceCounter("Processor", "% Processor Time", "_Total");
141 processorPercentPerfCounter = new PerfCounterControl(tempPC);
142 // A long time bug in mono is that CPU percent is reported as CPU percent idle. Windows reports CPU percent busy.
143 tempStat = new Stat(tempName, tempName, "", "percent", CategoryServer, ContainerProcessor,
144 StatType.Pull, (s) => { GetNextValue(s, processorPercentPerfCounter, Util.IsWindows() ? 1 : -1); },
145 StatVerbosity.Info);
146 StatsManager.RegisterStat(tempStat);
147 RegisteredStats.Add(tempName, tempStat);
148
149 MakeStat("TotalProcessorTime", null, "sec", ContainerProcessor,
150 (s) => { s.Value = Process.GetCurrentProcess().TotalProcessorTime.TotalSeconds; });
151
152 MakeStat("UserProcessorTime", null, "sec", ContainerProcessor,
153 (s) => { s.Value = Process.GetCurrentProcess().UserProcessorTime.TotalSeconds; });
154
155 MakeStat("PrivilegedProcessorTime", null, "sec", ContainerProcessor,
156 (s) => { s.Value = Process.GetCurrentProcess().PrivilegedProcessorTime.TotalSeconds; });
157
158 MakeStat("Threads", null, "threads", ContainerProcessor,
159 (s) => { s.Value = Process.GetCurrentProcess().Threads.Count; });
160 }
161 catch (Exception e)
162 {
163 m_log.ErrorFormat("{0} Exception creating 'Process': {1}", LogHeader, e);
164 }
165
166 MakeStat("BuiltinThreadpoolWorkerThreadsAvailable", null, "threads", ContainerThreadpool,
167 s =>
168 {
169 int workerThreads, iocpThreads;
170 ThreadPool.GetAvailableThreads(out workerThreads, out iocpThreads);
171 s.Value = workerThreads;
172 });
173
174 MakeStat("BuiltinThreadpoolIOCPThreadsAvailable", null, "threads", ContainerThreadpool,
175 s =>
176 {
177 int workerThreads, iocpThreads;
178 ThreadPool.GetAvailableThreads(out workerThreads, out iocpThreads);
179 s.Value = iocpThreads;
180 });
181
182 if (Util.FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool && Util.GetSmartThreadPoolInfo() != null)
183 {
184 MakeStat("STPMaxThreads", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().MaxThreads);
185 MakeStat("STPMinThreads", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().MinThreads);
186 MakeStat("STPConcurrency", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().MaxConcurrentWorkItems);
187 MakeStat("STPActiveThreads", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().ActiveThreads);
188 MakeStat("STPInUseThreads", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().InUseThreads);
189 MakeStat("STPWorkItemsWaiting", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().WaitingCallbacks);
190 }
191
192 MakeStat(
193 "HTTPRequestsMade",
194 "Number of outbound HTTP requests made",
195 "requests",
196 ContainerNetwork,
197 s => s.Value = WebUtil.RequestNumber,
198 MeasuresOfInterest.AverageChangeOverTime);
199
200 try
201 {
202 List<string> okInterfaceTypes = new List<string>(NetworkInterfaceTypes.Split(','));
203
204 IEnumerable<NetworkInterface> nics = NetworkInterface.GetAllNetworkInterfaces();
205 foreach (NetworkInterface nic in nics)
206 {
207 if (nic.OperationalStatus != OperationalStatus.Up)
208 continue;
209
210 string nicInterfaceType = nic.NetworkInterfaceType.ToString();
211 if (!okInterfaceTypes.Contains(nicInterfaceType))
212 {
213 m_log.DebugFormat("{0} Not including stats for network interface '{1}' of type '{2}'.",
214 LogHeader, nic.Name, nicInterfaceType);
215 m_log.DebugFormat("{0} To include, add to comma separated list in [Monitoring]NetworkInterfaceTypes={1}",
216 LogHeader, NetworkInterfaceTypes);
217 continue;
218 }
219
220 if (nic.Supports(NetworkInterfaceComponent.IPv4))
221 {
222 IPv4InterfaceStatistics nicStats = nic.GetIPv4Statistics();
223 if (nicStats != null)
224 {
225 MakeStat("BytesRcvd/" + nic.Name, nic.Name, "KB", ContainerNetwork,
226 (s) => { LookupNic(s, (ns) => { return ns.BytesReceived; }, 1024.0); });
227 MakeStat("BytesSent/" + nic.Name, nic.Name, "KB", ContainerNetwork,
228 (s) => { LookupNic(s, (ns) => { return ns.BytesSent; }, 1024.0); });
229 MakeStat("TotalBytes/" + nic.Name, nic.Name, "KB", ContainerNetwork,
230 (s) => { LookupNic(s, (ns) => { return ns.BytesSent + ns.BytesReceived; }, 1024.0); });
231 }
232 }
233 // TODO: add IPv6 (it may actually happen someday)
234 }
235 }
236 catch (Exception e)
237 {
238 m_log.ErrorFormat("{0} Exception creating 'Network Interface': {1}", LogHeader, e);
239 }
240
241 MakeStat("ProcessMemory", null, "MB", ContainerMemory,
242 (s) => { s.Value = Math.Round(Process.GetCurrentProcess().WorkingSet64 / 1024d / 1024d, 3); });
243 MakeStat("HeapMemory", null, "MB", ContainerMemory,
244 (s) => { s.Value = Math.Round(GC.GetTotalMemory(false) / 1024d / 1024d, 3); });
245 MakeStat("LastHeapAllocationRate", null, "MB/sec", ContainerMemory,
246 (s) => { s.Value = Math.Round(MemoryWatchdog.LastHeapAllocationRate * 1000d / 1024d / 1024d, 3); });
247 MakeStat("AverageHeapAllocationRate", null, "MB/sec", ContainerMemory,
248 (s) => { s.Value = Math.Round(MemoryWatchdog.AverageHeapAllocationRate * 1000d / 1024d / 1024d, 3); });
249 }
250
251 // Notes on performance counters:
252 // "How To Read Performance Counters": http://blogs.msdn.com/b/bclteam/archive/2006/06/02/618156.aspx
253 // "How to get the CPU Usage in C#": http://stackoverflow.com/questions/278071/how-to-get-the-cpu-usage-in-c
254 // "Mono Performance Counters": http://www.mono-project.com/Mono_Performance_Counters
255 private delegate double PerfCounterNextValue();
256 private void GetNextValue(Stat stat, PerfCounterControl perfControl)
257 {
258 GetNextValue(stat, perfControl, 1.0);
259 }
260 private void GetNextValue(Stat stat, PerfCounterControl perfControl, double factor)
261 {
262 if (Util.EnvironmentTickCountSubtract(perfControl.lastFetch) > performanceCounterSampleInterval)
263 {
264 if (perfControl != null && perfControl.perfCounter != null)
265 {
266 try
267 {
268 // Kludge for factor to run double duty. If -1, subtract the value from one
269 if (factor == -1)
270 stat.Value = 1 - perfControl.perfCounter.NextValue();
271 else
272 stat.Value = perfControl.perfCounter.NextValue() / factor;
273 }
274 catch (Exception e)
275 {
276 m_log.ErrorFormat("{0} Exception on NextValue fetching {1}: {2}", LogHeader, stat.Name, e);
277 }
278 perfControl.lastFetch = Util.EnvironmentTickCount();
279 }
280 }
281 }
282
283 // Lookup the nic that goes with this stat and set the value by using a fetch action.
284 // Not sure about closure with delegates inside delegates.
285 private delegate double GetIPv4StatValue(IPv4InterfaceStatistics interfaceStat);
286 private void LookupNic(Stat stat, GetIPv4StatValue getter, double factor)
287 {
288 // Get the one nic that has the name of this stat
289 IEnumerable<NetworkInterface> nics = NetworkInterface.GetAllNetworkInterfaces().Where(
290 (network) => network.Name == stat.Description);
291 try
292 {
293 foreach (NetworkInterface nic in nics)
294 {
295 IPv4InterfaceStatistics intrStats = nic.GetIPv4Statistics();
296 if (intrStats != null)
297 {
298 double newVal = Math.Round(getter(intrStats) / factor, 3);
299 stat.Value = newVal;
300 }
301 break;
302 }
303 }
304 catch
305 {
306 // There are times interfaces go away so we just won't update the stat for this
307 m_log.ErrorFormat("{0} Exception fetching stat on interface '{1}'", LogHeader, stat.Description);
308 }
309 }
310 }
311
312 public class ServerStatsAggregator : Stat
313 {
314 public ServerStatsAggregator(
315 string shortName,
316 string name,
317 string description,
318 string unitName,
319 string category,
320 string container
321 )
322 : base(
323 shortName,
324 name,
325 description,
326 unitName,
327 category,
328 container,
329 StatType.Push,
330 MeasuresOfInterest.None,
331 null,
332 StatVerbosity.Info)
333 {
334 }
335 public override string ToConsoleString()
336 {
337 StringBuilder sb = new StringBuilder();
338
339 return sb.ToString();
340 }
341
342 public override OSDMap ToOSDMap()
343 {
344 OSDMap ret = new OSDMap();
345
346 return ret;
347 }
348 }
349}
diff --git a/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs
index 6a68322..f6f458d 100644
--- a/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs
+++ b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs
@@ -27,6 +27,7 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Linq;
30using System.Text; 31using System.Text;
31using OpenMetaverse; 32using OpenMetaverse;
32using OpenMetaverse.StructuredData; 33using OpenMetaverse.StructuredData;
@@ -39,8 +40,6 @@ namespace OpenSim.Framework.Monitoring
39 /// </summary> 40 /// </summary>
40 public class SimExtraStatsCollector : BaseStatsCollector 41 public class SimExtraStatsCollector : BaseStatsCollector
41 { 42 {
42 private long abnormalClientThreadTerminations;
43
44// private long assetsInCache; 43// private long assetsInCache;
45// private long texturesInCache; 44// private long texturesInCache;
46// private long assetCacheMemoryUsage; 45// private long assetCacheMemoryUsage;
@@ -73,11 +72,6 @@ namespace OpenSim.Framework.Monitoring
73 private volatile float activeScripts; 72 private volatile float activeScripts;
74 private volatile float scriptLinesPerSecond; 73 private volatile float scriptLinesPerSecond;
75 74
76 /// <summary>
77 /// Number of times that a client thread terminated because of an exception
78 /// </summary>
79 public long AbnormalClientThreadTerminations { get { return abnormalClientThreadTerminations; } }
80
81// /// <summary> 75// /// <summary>
82// /// These statistics are being collected by push rather than pull. Pull would be simpler, but I had the 76// /// These statistics are being collected by push rather than pull. Pull would be simpler, but I had the
83// /// notion of providing some flow statistics (which pull wouldn't give us). Though admittedly these 77// /// notion of providing some flow statistics (which pull wouldn't give us). Though admittedly these
@@ -166,11 +160,6 @@ namespace OpenSim.Framework.Monitoring
166 private IDictionary<UUID, PacketQueueStatsCollector> packetQueueStatsCollectors 160 private IDictionary<UUID, PacketQueueStatsCollector> packetQueueStatsCollectors
167 = new Dictionary<UUID, PacketQueueStatsCollector>(); 161 = new Dictionary<UUID, PacketQueueStatsCollector>();
168 162
169 public void AddAbnormalClientThreadTermination()
170 {
171 abnormalClientThreadTerminations++;
172 }
173
174// public void AddAsset(AssetBase asset) 163// public void AddAsset(AssetBase asset)
175// { 164// {
176// assetsInCache++; 165// assetsInCache++;
@@ -324,10 +313,12 @@ Asset service request failures: {3}" + Environment.NewLine,
324 sb.Append(Environment.NewLine); 313 sb.Append(Environment.NewLine);
325 sb.Append("CONNECTION STATISTICS"); 314 sb.Append("CONNECTION STATISTICS");
326 sb.Append(Environment.NewLine); 315 sb.Append(Environment.NewLine);
327 sb.Append( 316
328 string.Format( 317 List<Stat> stats = StatsManager.GetStatsFromEachContainer("clientstack", "ClientLogoutsDueToNoReceives");
329 "Abnormal client thread terminations: {0}" + Environment.NewLine, 318
330 abnormalClientThreadTerminations)); 319 sb.AppendFormat(
320 "Client logouts due to no data receive timeout: {0}\n\n",
321 stats != null ? stats.Sum(s => s.Value).ToString() : "unknown");
331 322
332// sb.Append(Environment.NewLine); 323// sb.Append(Environment.NewLine);
333// sb.Append("INVENTORY STATISTICS"); 324// sb.Append("INVENTORY STATISTICS");
@@ -338,7 +329,7 @@ Asset service request failures: {3}" + Environment.NewLine,
338// InventoryServiceRetrievalFailures)); 329// InventoryServiceRetrievalFailures));
339 330
340 sb.Append(Environment.NewLine); 331 sb.Append(Environment.NewLine);
341 sb.Append("FRAME STATISTICS"); 332 sb.Append("SAMPLE FRAME STATISTICS");
342 sb.Append(Environment.NewLine); 333 sb.Append(Environment.NewLine);
343 sb.Append("Dilatn SimFPS PhyFPS AgntUp RootAg ChldAg Prims AtvPrm AtvScr ScrLPS"); 334 sb.Append("Dilatn SimFPS PhyFPS AgntUp RootAg ChldAg Prims AtvPrm AtvScr ScrLPS");
344 sb.Append(Environment.NewLine); 335 sb.Append(Environment.NewLine);
diff --git a/OpenSim/Framework/Monitoring/Stats/CounterStat.cs b/OpenSim/Framework/Monitoring/Stats/CounterStat.cs
index caea30d..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
@@ -224,5 +88,32 @@ public class CounterStat : Stat
224 } 88 }
225 } 89 }
226 } 90 }
91
92 // CounterStat is a basic stat plus histograms
93 public override OSDMap ToOSDMap()
94 {
95 // Get the foundational instance
96 OSDMap map = base.ToOSDMap();
97
98 map["StatType"] = "CounterStat";
99
100 // If there are any histograms, add a new field that is an array of histograms as OSDMaps
101 if (m_histograms.Count > 0)
102 {
103 lock (counterLock)
104 {
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 }
114 }
115 }
116 return map;
117 }
227} 118}
228} 119}
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 2e7665f..e095801 100644
--- a/OpenSim/Framework/Monitoring/Stats/Stat.cs
+++ b/OpenSim/Framework/Monitoring/Stats/Stat.cs
@@ -27,8 +27,10 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Linq;
31using System.Reflection;
30using System.Text; 32using System.Text;
31 33using log4net;
32using OpenMetaverse.StructuredData; 34using OpenMetaverse.StructuredData;
33 35
34namespace OpenSim.Framework.Monitoring 36namespace OpenSim.Framework.Monitoring
@@ -38,6 +40,10 @@ namespace OpenSim.Framework.Monitoring
38 /// </summary> 40 /// </summary>
39 public class Stat : IDisposable 41 public class Stat : IDisposable
40 { 42 {
43// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
44
45 public static readonly char[] DisallowedShortNameCharacters = { '.' };
46
41 /// <summary> 47 /// <summary>
42 /// Category of this stat (e.g. cache, scene, etc). 48 /// Category of this stat (e.g. cache, scene, etc).
43 /// </summary> 49 /// </summary>
@@ -95,7 +101,7 @@ namespace OpenSim.Framework.Monitoring
95 /// <remarks> 101 /// <remarks>
96 /// Will be null if no measures of interest require samples. 102 /// Will be null if no measures of interest require samples.
97 /// </remarks> 103 /// </remarks>
98 private static Queue<double> m_samples; 104 private Queue<double> m_samples;
99 105
100 /// <summary> 106 /// <summary>
101 /// Maximum number of statistical samples. 107 /// Maximum number of statistical samples.
@@ -162,6 +168,12 @@ namespace OpenSim.Framework.Monitoring
162 throw new Exception( 168 throw new Exception(
163 string.Format("Stat cannot be in category '{0}' since this is reserved for a subcommand", category)); 169 string.Format("Stat cannot be in category '{0}' since this is reserved for a subcommand", category));
164 170
171 foreach (char c in DisallowedShortNameCharacters)
172 {
173 if (shortName.IndexOf(c) != -1)
174 throw new Exception(string.Format("Stat name {0} cannot contain character {1}", shortName, c));
175 }
176
165 ShortName = shortName; 177 ShortName = shortName;
166 Name = name; 178 Name = name;
167 Description = description; 179 Description = description;
@@ -204,6 +216,8 @@ namespace OpenSim.Framework.Monitoring
204 if (m_samples.Count >= m_maxSamples) 216 if (m_samples.Count >= m_maxSamples)
205 m_samples.Dequeue(); 217 m_samples.Dequeue();
206 218
219// m_log.DebugFormat("[STAT]: Recording value {0} for {1}", newValue, Name);
220
207 m_samples.Enqueue(newValue); 221 m_samples.Enqueue(newValue);
208 } 222 }
209 } 223 }
@@ -211,7 +225,13 @@ namespace OpenSim.Framework.Monitoring
211 public virtual string ToConsoleString() 225 public virtual string ToConsoleString()
212 { 226 {
213 StringBuilder sb = new StringBuilder(); 227 StringBuilder sb = new StringBuilder();
214 sb.AppendFormat("{0}.{1}.{2} : {3} {4}", Category, Container, ShortName, Value, UnitName); 228 sb.AppendFormat(
229 "{0}.{1}.{2} : {3}{4}",
230 Category,
231 Container,
232 ShortName,
233 Value,
234 string.IsNullOrEmpty(UnitName) ? "" : string.Format(" {0}", UnitName));
215 235
216 AppendMeasuresOfInterest(sb); 236 AppendMeasuresOfInterest(sb);
217 237
@@ -221,6 +241,8 @@ namespace OpenSim.Framework.Monitoring
221 public virtual OSDMap ToOSDMap() 241 public virtual OSDMap ToOSDMap()
222 { 242 {
223 OSDMap ret = new OSDMap(); 243 OSDMap ret = new OSDMap();
244 ret.Add("StatType", "Stat"); // used by overloading classes to denote type of stat
245
224 ret.Add("Category", OSD.FromString(Category)); 246 ret.Add("Category", OSD.FromString(Category));
225 ret.Add("Container", OSD.FromString(Container)); 247 ret.Add("Container", OSD.FromString(Container));
226 ret.Add("ShortName", OSD.FromString(ShortName)); 248 ret.Add("ShortName", OSD.FromString(ShortName));
@@ -229,31 +251,74 @@ namespace OpenSim.Framework.Monitoring
229 ret.Add("UnitName", OSD.FromString(UnitName)); 251 ret.Add("UnitName", OSD.FromString(UnitName));
230 ret.Add("Value", OSD.FromReal(Value)); 252 ret.Add("Value", OSD.FromReal(Value));
231 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 }
260
232 return ret; 261 return ret;
233 } 262 }
234 263
235 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)
236 { 267 {
237 if ((MeasuresOfInterest & MeasuresOfInterest.AverageChangeOverTime) 268 bool ret = false;
238 == MeasuresOfInterest.AverageChangeOverTime) 269 lastChangeOverTime = 0;
270 averageChangeOverTime = 0;
271
272 if ((MeasuresOfInterest & MeasuresOfInterest.AverageChangeOverTime) == MeasuresOfInterest.AverageChangeOverTime)
239 { 273 {
240 double totalChange = 0; 274 double totalChange = 0;
275 double? penultimateSample = null;
241 double? lastSample = null; 276 double? lastSample = null;
242 277
243 lock (m_samples) 278 lock (m_samples)
244 { 279 {
280 // m_log.DebugFormat(
281 // "[STAT]: Samples for {0} are {1}",
282 // Name, string.Join(",", m_samples.Select(s => s.ToString()).ToArray()));
283
245 foreach (double s in m_samples) 284 foreach (double s in m_samples)
246 { 285 {
247 if (lastSample != null) 286 if (lastSample != null)
248 totalChange += s - (double)lastSample; 287 totalChange += s - (double)lastSample;
249 288
289 penultimateSample = lastSample;
250 lastSample = s; 290 lastSample = s;
251 } 291 }
252 } 292 }
253 293
294 if (lastSample != null && penultimateSample != null)
295 {
296 lastChangeOverTime
297 = ((double)lastSample - (double)penultimateSample) / (Watchdog.WATCHDOG_INTERVAL_MS / 1000);
298 }
299
254 int divisor = m_samples.Count <= 1 ? 1 : m_samples.Count - 1; 300 int divisor = m_samples.Count <= 1 ? 1 : m_samples.Count - 1;
255 301
256 sb.AppendFormat(", {0:0.##}{1}/s", totalChange / divisor / (Watchdog.WATCHDOG_INTERVAL_MS / 1000), UnitName); 302 averageChangeOverTime = totalChange / divisor / (Watchdog.WATCHDOG_INTERVAL_MS / 1000);
303 ret = true;
304 }
305
306 return ret;
307 }
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 {
316 sb.AppendFormat(
317 ", {0:0.##}{1}/s, {2:0.##}{3}/s",
318 lastChangeOverTime,
319 string.IsNullOrEmpty(UnitName) ? "" : string.Format(" {0}", UnitName),
320 averageChangeOverTime,
321 string.IsNullOrEmpty(UnitName) ? "" : string.Format(" {0}", UnitName));
257 } 322 }
258 } 323 }
259 } 324 }
diff --git a/OpenSim/Framework/Monitoring/StatsLogger.cs b/OpenSim/Framework/Monitoring/StatsLogger.cs
new file mode 100644
index 0000000..1e4fa11
--- /dev/null
+++ b/OpenSim/Framework/Monitoring/StatsLogger.cs
@@ -0,0 +1,108 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Reflection;
30using System.Timers;
31using log4net;
32
33namespace OpenSim.Framework.Monitoring
34{
35 /// <summary>
36 /// Provides a means to continuously log stats for debugging purposes.
37 /// </summary>
38 public static class StatsLogger
39 {
40 private static readonly ILog m_statsLog = LogManager.GetLogger("special.StatsLogger");
41
42 private static Timer m_loggingTimer;
43 private static int m_statsLogIntervalMs = 5000;
44
45 public static void RegisterConsoleCommands(ICommandConsole console)
46 {
47 console.Commands.AddCommand(
48 "Debug",
49 false,
50 "debug stats record",
51 "debug stats record start|stop",
52 "Control whether stats are being regularly recorded to a separate file.",
53 "For debug purposes. Experimental.",
54 HandleStatsRecordCommand);
55 }
56
57 public static void HandleStatsRecordCommand(string module, string[] cmd)
58 {
59 ICommandConsole con = MainConsole.Instance;
60
61 if (cmd.Length != 4)
62 {
63 con.Output("Usage: debug stats record start|stop");
64 return;
65 }
66
67 if (cmd[3] == "start")
68 {
69 Start();
70 con.OutputFormat("Now recording all stats to file every {0}ms", m_statsLogIntervalMs);
71 }
72 else if (cmd[3] == "stop")
73 {
74 Stop();
75 con.Output("Stopped recording stats to file.");
76 }
77 }
78
79 public static void Start()
80 {
81 if (m_loggingTimer != null)
82 Stop();
83
84 m_loggingTimer = new Timer(m_statsLogIntervalMs);
85 m_loggingTimer.AutoReset = false;
86 m_loggingTimer.Elapsed += Log;
87 m_loggingTimer.Start();
88 }
89
90 public static void Stop()
91 {
92 if (m_loggingTimer != null)
93 {
94 m_loggingTimer.Stop();
95 }
96 }
97
98 private static void Log(object sender, ElapsedEventArgs e)
99 {
100 m_statsLog.InfoFormat("*** STATS REPORT AT {0} ***", DateTime.Now);
101
102 foreach (string report in StatsManager.GetAllStatsReports())
103 m_statsLog.Info(report);
104
105 m_loggingTimer.Start();
106 }
107 }
108} \ No newline at end of file
diff --git a/OpenSim/Framework/Monitoring/StatsManager.cs b/OpenSim/Framework/Monitoring/StatsManager.cs
index 24db6d4..05ee4c5 100644
--- a/OpenSim/Framework/Monitoring/StatsManager.cs
+++ b/OpenSim/Framework/Monitoring/StatsManager.cs
@@ -26,15 +26,20 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections;
29using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Linq;
30using System.Text; 32using System.Text;
31 33
34using OpenSim.Framework;
35using OpenMetaverse.StructuredData;
36
32namespace OpenSim.Framework.Monitoring 37namespace OpenSim.Framework.Monitoring
33{ 38{
34 /// <summary> 39 /// <summary>
35 /// Singleton used to provide access to statistics reporters 40 /// Static class used to register/deregister/fetch statistics
36 /// </summary> 41 /// </summary>
37 public class StatsManager 42 public static class StatsManager
38 { 43 {
39 // Subcommand used to list other stats. 44 // Subcommand used to list other stats.
40 public const string AllSubCommand = "all"; 45 public const string AllSubCommand = "all";
@@ -54,13 +59,13 @@ namespace OpenSim.Framework.Monitoring
54 public static SortedDictionary<string, SortedDictionary<string, SortedDictionary<string, Stat>>> RegisteredStats 59 public static SortedDictionary<string, SortedDictionary<string, SortedDictionary<string, Stat>>> RegisteredStats
55 = new SortedDictionary<string, SortedDictionary<string, SortedDictionary<string, Stat>>>(); 60 = new SortedDictionary<string, SortedDictionary<string, SortedDictionary<string, Stat>>>();
56 61
57 private static AssetStatsCollector assetStats; 62// private static AssetStatsCollector assetStats;
58 private static UserStatsCollector userStats; 63// private static UserStatsCollector userStats;
59 private static SimExtraStatsCollector simExtraStats = new SimExtraStatsCollector(); 64// private static SimExtraStatsCollector simExtraStats = new SimExtraStatsCollector();
60 65
61 public static AssetStatsCollector AssetStats { get { return assetStats; } } 66// public static AssetStatsCollector AssetStats { get { return assetStats; } }
62 public static UserStatsCollector UserStats { get { return userStats; } } 67// public static UserStatsCollector UserStats { get { return userStats; } }
63 public static SimExtraStatsCollector SimExtraStats { get { return simExtraStats; } } 68 public static SimExtraStatsCollector SimExtraStats { get; set; }
64 69
65 public static void RegisterConsoleCommands(ICommandConsole console) 70 public static void RegisterConsoleCommands(ICommandConsole console)
66 { 71 {
@@ -68,14 +73,18 @@ namespace OpenSim.Framework.Monitoring
68 "General", 73 "General",
69 false, 74 false,
70 "show stats", 75 "show stats",
71 "show stats [list|all|<category>]", 76 "show stats [list|all|(<category>[.<container>])+",
72 "Show statistical information for this server", 77 "Show statistical information for this server",
73 "If no final argument is specified then legacy statistics information is currently shown.\n" 78 "If no final argument is specified then legacy statistics information is currently shown.\n"
74 + "If list is specified then statistic categories are shown.\n" 79 + "'list' argument will show statistic categories.\n"
75 + "If all is specified then all registered statistics are shown.\n" 80 + "'all' will show all statistics.\n"
76 + "If a category name is specified then only statistics from that category are shown.\n" 81 + "A <category> name will show statistics from that category.\n"
82 + "A <category>.<container> name will show statistics from that category in that container.\n"
83 + "More than one name can be given separated by spaces.\n"
77 + "THIS STATS FACILITY IS EXPERIMENTAL AND DOES NOT YET CONTAIN ALL STATS", 84 + "THIS STATS FACILITY IS EXPERIMENTAL AND DOES NOT YET CONTAIN ALL STATS",
78 HandleShowStatsCommand); 85 HandleShowStatsCommand);
86
87 StatsLogger.RegisterConsoleCommands(console);
79 } 88 }
80 89
81 public static void HandleShowStatsCommand(string module, string[] cmd) 90 public static void HandleShowStatsCommand(string module, string[] cmd)
@@ -84,43 +93,47 @@ namespace OpenSim.Framework.Monitoring
84 93
85 if (cmd.Length > 2) 94 if (cmd.Length > 2)
86 { 95 {
87 var categoryName = cmd[2]; 96 foreach (string name in cmd.Skip(2))
88 var containerName = cmd.Length > 3 ? cmd[3] : String.Empty;
89
90 if (categoryName == AllSubCommand)
91 { 97 {
92 foreach (var category in RegisteredStats.Values) 98 string[] components = name.Split('.');
99
100 string categoryName = components[0];
101 string containerName = components.Length > 1 ? components[1] : null;
102
103 if (categoryName == AllSubCommand)
93 { 104 {
94 OutputCategoryStatsToConsole(con, category); 105 OutputAllStatsToConsole(con);
95 } 106 }
96 } 107 else if (categoryName == ListSubCommand)
97 else if (categoryName == ListSubCommand)
98 {
99 con.Output("Statistic categories available are:");
100 foreach (string category in RegisteredStats.Keys)
101 con.OutputFormat(" {0}", category);
102 }
103 else
104 {
105 SortedDictionary<string, SortedDictionary<string, Stat>> category;
106 if (!RegisteredStats.TryGetValue(categoryName, out category))
107 { 108 {
108 con.OutputFormat("No such category as {0}", categoryName); 109 con.Output("Statistic categories available are:");
110 foreach (string category in RegisteredStats.Keys)
111 con.OutputFormat(" {0}", category);
109 } 112 }
110 else 113 else
111 { 114 {
112 if (String.IsNullOrEmpty(containerName)) 115 SortedDictionary<string, SortedDictionary<string, Stat>> category;
113 OutputCategoryStatsToConsole(con, category); 116 if (!RegisteredStats.TryGetValue(categoryName, out category))
117 {
118 con.OutputFormat("No such category as {0}", categoryName);
119 }
114 else 120 else
115 { 121 {
116 SortedDictionary<string, Stat> container; 122 if (String.IsNullOrEmpty(containerName))
117 if (category.TryGetValue(containerName, out container))
118 { 123 {
119 OutputContainerStatsToConsole(con, container); 124 OutputCategoryStatsToConsole(con, category);
120 } 125 }
121 else 126 else
122 { 127 {
123 con.OutputFormat("No such container {0} in category {1}", containerName, categoryName); 128 SortedDictionary<string, Stat> container;
129 if (category.TryGetValue(containerName, out container))
130 {
131 OutputContainerStatsToConsole(con, container);
132 }
133 else
134 {
135 con.OutputFormat("No such container {0} in category {1}", containerName, categoryName);
136 }
124 } 137 }
125 } 138 }
126 } 139 }
@@ -129,51 +142,187 @@ namespace OpenSim.Framework.Monitoring
129 else 142 else
130 { 143 {
131 // Legacy 144 // Legacy
132 con.Output(SimExtraStats.Report()); 145 if (SimExtraStats != null)
146 con.Output(SimExtraStats.Report());
147 else
148 OutputAllStatsToConsole(con);
133 } 149 }
134 } 150 }
135 151
152 public static List<string> GetAllStatsReports()
153 {
154 List<string> reports = new List<string>();
155
156 foreach (var category in RegisteredStats.Values)
157 reports.AddRange(GetCategoryStatsReports(category));
158
159 return reports;
160 }
161
162 private static void OutputAllStatsToConsole(ICommandConsole con)
163 {
164 foreach (string report in GetAllStatsReports())
165 con.Output(report);
166 }
167
168 private static List<string> GetCategoryStatsReports(
169 SortedDictionary<string, SortedDictionary<string, Stat>> category)
170 {
171 List<string> reports = new List<string>();
172
173 foreach (var container in category.Values)
174 reports.AddRange(GetContainerStatsReports(container));
175
176 return reports;
177 }
178
136 private static void OutputCategoryStatsToConsole( 179 private static void OutputCategoryStatsToConsole(
137 ICommandConsole con, SortedDictionary<string, SortedDictionary<string, Stat>> category) 180 ICommandConsole con, SortedDictionary<string, SortedDictionary<string, Stat>> category)
138 { 181 {
139 foreach (var container in category.Values) 182 foreach (string report in GetCategoryStatsReports(category))
140 { 183 con.Output(report);
141 OutputContainerStatsToConsole(con, container);
142 }
143 } 184 }
144 185
145 private static void OutputContainerStatsToConsole( ICommandConsole con, SortedDictionary<string, Stat> container) 186 private static List<string> GetContainerStatsReports(SortedDictionary<string, Stat> container)
146 { 187 {
188 List<string> reports = new List<string>();
189
147 foreach (Stat stat in container.Values) 190 foreach (Stat stat in container.Values)
148 { 191 reports.Add(stat.ToConsoleString());
149 con.Output(stat.ToConsoleString()); 192
150 } 193 return reports;
151 } 194 }
152 195
153 /// <summary> 196 private static void OutputContainerStatsToConsole(
154 /// Start collecting statistics related to assets. 197 ICommandConsole con, SortedDictionary<string, Stat> container)
155 /// Should only be called once. 198 {
156 /// </summary> 199 foreach (string report in GetContainerStatsReports(container))
157 public static AssetStatsCollector StartCollectingAssetStats() 200 con.Output(report);
201 }
202
203 // Creates an OSDMap of the format:
204 // { categoryName: {
205 // containerName: {
206 // statName: {
207 // "Name": name,
208 // "ShortName": shortName,
209 // ...
210 // },
211 // statName: {
212 // "Name": name,
213 // "ShortName": shortName,
214 // ...
215 // },
216 // ...
217 // },
218 // containerName: {
219 // ...
220 // },
221 // ...
222 // },
223 // categoryName: {
224 // ...
225 // },
226 // ...
227 // }
228 // The passed in parameters will filter the categories, containers and stats returned. If any of the
229 // parameters are either EmptyOrNull or the AllSubCommand value, all of that type will be returned.
230 // Case matters.
231 public static OSDMap GetStatsAsOSDMap(string pCategoryName, string pContainerName, string pStatName)
158 { 232 {
159 assetStats = new AssetStatsCollector(); 233 OSDMap map = new OSDMap();
234
235 foreach (string catName in RegisteredStats.Keys)
236 {
237 // Do this category if null spec, "all" subcommand or category name matches passed parameter.
238 // Skip category if none of the above.
239 if (!(String.IsNullOrEmpty(pCategoryName) || pCategoryName == AllSubCommand || pCategoryName == catName))
240 continue;
160 241
161 return assetStats; 242 OSDMap contMap = new OSDMap();
243 foreach (string contName in RegisteredStats[catName].Keys)
244 {
245 if (!(string.IsNullOrEmpty(pContainerName) || pContainerName == AllSubCommand || pContainerName == contName))
246 continue;
247
248 OSDMap statMap = new OSDMap();
249
250 SortedDictionary<string, Stat> theStats = RegisteredStats[catName][contName];
251 foreach (string statName in theStats.Keys)
252 {
253 if (!(String.IsNullOrEmpty(pStatName) || pStatName == AllSubCommand || pStatName == statName))
254 continue;
255
256 statMap.Add(statName, theStats[statName].ToOSDMap());
257 }
258
259 contMap.Add(contName, statMap);
260 }
261 map.Add(catName, contMap);
262 }
263
264 return map;
162 } 265 }
163 266
164 /// <summary> 267 public static Hashtable HandleStatsRequest(Hashtable request)
165 /// Start collecting statistics related to users.
166 /// Should only be called once.
167 /// </summary>
168 public static UserStatsCollector StartCollectingUserStats()
169 { 268 {
170 userStats = new UserStatsCollector(); 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 }
171 289
172 return userStats; 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;
173 } 300 }
174 301
302// /// <summary>
303// /// Start collecting statistics related to assets.
304// /// Should only be called once.
305// /// </summary>
306// public static AssetStatsCollector StartCollectingAssetStats()
307// {
308// assetStats = new AssetStatsCollector();
309//
310// return assetStats;
311// }
312//
313// /// <summary>
314// /// Start collecting statistics related to users.
315// /// Should only be called once.
316// /// </summary>
317// public static UserStatsCollector StartCollectingUserStats()
318// {
319// userStats = new UserStatsCollector();
320//
321// return userStats;
322// }
323
175 /// <summary> 324 /// <summary>
176 /// Registers a statistic. 325 /// Register a statistic.
177 /// </summary> 326 /// </summary>
178 /// <param name='stat'></param> 327 /// <param name='stat'></param>
179 /// <returns></returns> 328 /// <returns></returns>
@@ -187,7 +336,7 @@ namespace OpenSim.Framework.Monitoring
187 // Stat name is not unique across category/container/shortname key. 336 // Stat name is not unique across category/container/shortname key.
188 // XXX: For now just return false. This is to avoid problems in regression tests where all tests 337 // XXX: For now just return false. This is to avoid problems in regression tests where all tests
189 // in a class are run in the same instance of the VM. 338 // in a class are run in the same instance of the VM.
190 if (TryGetStat(stat, out category, out container)) 339 if (TryGetStatParents(stat, out category, out container))
191 return false; 340 return false;
192 341
193 // We take a copy-on-write approach here of replacing dictionaries when keys are added or removed. 342 // We take a copy-on-write approach here of replacing dictionaries when keys are added or removed.
@@ -223,7 +372,7 @@ namespace OpenSim.Framework.Monitoring
223 372
224 lock (RegisteredStats) 373 lock (RegisteredStats)
225 { 374 {
226 if (!TryGetStat(stat, out category, out container)) 375 if (!TryGetStatParents(stat, out category, out container))
227 return false; 376 return false;
228 377
229 newContainer = new SortedDictionary<string, Stat>(container); 378 newContainer = new SortedDictionary<string, Stat>(container);
@@ -239,12 +388,67 @@ namespace OpenSim.Framework.Monitoring
239 } 388 }
240 } 389 }
241 390
242 public static bool TryGetStats(string category, out SortedDictionary<string, SortedDictionary<string, Stat>> stats) 391 public static bool TryGetStat(string category, string container, string statShortName, out Stat stat)
243 { 392 {
244 return RegisteredStats.TryGetValue(category, out stats); 393 stat = null;
394 SortedDictionary<string, SortedDictionary<string, Stat>> categoryStats;
395
396 lock (RegisteredStats)
397 {
398 if (!TryGetStatsForCategory(category, out categoryStats))
399 return false;
400
401 SortedDictionary<string, Stat> containerStats;
402
403 if (!categoryStats.TryGetValue(container, out containerStats))
404 return false;
405
406 return containerStats.TryGetValue(statShortName, out stat);
407 }
408 }
409
410 public static bool TryGetStatsForCategory(
411 string category, out SortedDictionary<string, SortedDictionary<string, Stat>> stats)
412 {
413 lock (RegisteredStats)
414 return RegisteredStats.TryGetValue(category, out stats);
415 }
416
417 /// <summary>
418 /// Get the same stat for each container in a given category.
419 /// </summary>
420 /// <returns>
421 /// The stats if there were any to fetch. Otherwise null.
422 /// </returns>
423 /// <param name='category'></param>
424 /// <param name='statShortName'></param>
425 public static List<Stat> GetStatsFromEachContainer(string category, string statShortName)
426 {
427 SortedDictionary<string, SortedDictionary<string, Stat>> categoryStats;
428
429 lock (RegisteredStats)
430 {
431 if (!RegisteredStats.TryGetValue(category, out categoryStats))
432 return null;
433
434 List<Stat> stats = null;
435
436 foreach (SortedDictionary<string, Stat> containerStats in categoryStats.Values)
437 {
438 if (containerStats.ContainsKey(statShortName))
439 {
440 if (stats == null)
441 stats = new List<Stat>();
442
443 stats.Add(containerStats[statShortName]);
444 }
445 }
446
447 return stats;
448 }
245 } 449 }
246 450
247 public static bool TryGetStat( 451 public static bool TryGetStatParents(
248 Stat stat, 452 Stat stat,
249 out SortedDictionary<string, SortedDictionary<string, Stat>> category, 453 out SortedDictionary<string, SortedDictionary<string, Stat>> category,
250 out SortedDictionary<string, Stat> container) 454 out SortedDictionary<string, Stat> container)
diff --git a/OpenSim/Framework/Monitoring/Watchdog.cs b/OpenSim/Framework/Monitoring/Watchdog.cs
index 69d2db5..32724ec 100644
--- a/OpenSim/Framework/Monitoring/Watchdog.cs
+++ b/OpenSim/Framework/Monitoring/Watchdog.cs
@@ -380,6 +380,7 @@ namespace OpenSim.Framework.Monitoring
380 if (MemoryWatchdog.Enabled) 380 if (MemoryWatchdog.Enabled)
381 MemoryWatchdog.Update(); 381 MemoryWatchdog.Update();
382 382
383 ChecksManager.CheckChecks();
383 StatsManager.RecordStats(); 384 StatsManager.RecordStats();
384 385
385 m_watchdogTimer.Start(); 386 m_watchdogTimer.Start();
diff --git a/OpenSim/Framework/PermissionsUtil.cs b/OpenSim/Framework/PermissionsUtil.cs
new file mode 100644
index 0000000..d785a78
--- /dev/null
+++ b/OpenSim/Framework/PermissionsUtil.cs
@@ -0,0 +1,87 @@
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.Reflection;
31using System.Text;
32using log4net;
33
34namespace OpenSim.Framework
35{
36 public static class PermissionsUtil
37 {
38 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
39
40 /// <summary>
41 /// Logs permissions flags. Useful when debugging permission problems.
42 /// </summary>
43 /// <param name="message"></param>
44 public static void LogPermissions(String name, String message, uint basePerm, uint curPerm, uint nextPerm)
45 {
46 m_log.DebugFormat("Permissions of \"{0}\" at \"{1}\": Base {2} ({3:X4}), Current {4} ({5:X4}), NextOwner {6} ({7:X4})",
47 name, message,
48 PermissionsToString(basePerm), basePerm, PermissionsToString(curPerm), curPerm, PermissionsToString(nextPerm), nextPerm);
49 }
50
51 /// <summary>
52 /// Converts a permissions bit-mask to a string (e.g., "MCT").
53 /// </summary>
54 private static string PermissionsToString(uint perms)
55 {
56 string str = "";
57 if ((perms & (int)PermissionMask.Modify) != 0)
58 str += "M";
59 if ((perms & (int)PermissionMask.Copy) != 0)
60 str += "C";
61 if ((perms & (int)PermissionMask.Transfer) != 0)
62 str += "T";
63 if (str == "")
64 str = ".";
65 return str;
66 }
67
68 /// <summary>
69 /// Applies an object's folded permissions to its regular permissions.
70 /// </summary>
71 /// <param name="foldedPerms">The folded permissions. Only the lowest 7 bits are examined.</param>
72 /// <param name="mainPerms">The permissions variable to modify.</param>
73 public static void ApplyFoldedPermissions(uint foldedPerms, ref uint mainPerms)
74 {
75 if ((foldedPerms & 7) == 0)
76 return; // assume that if the folded permissions are 0 then this means that they weren't actually recorded
77
78 if ((foldedPerms & ((uint)PermissionMask.Copy >> 13)) == 0)
79 mainPerms &= ~(uint)PermissionMask.Copy;
80 if ((foldedPerms & ((uint)PermissionMask.Transfer >> 13)) == 0)
81 mainPerms &= ~(uint)PermissionMask.Transfer;
82 if ((foldedPerms & ((uint)PermissionMask.Modify >> 13)) == 0)
83 mainPerms &= ~(uint)PermissionMask.Modify;
84 }
85
86 }
87}
diff --git a/OpenSim/Framework/PrimitiveBaseShape.cs b/OpenSim/Framework/PrimitiveBaseShape.cs
index df928dc..6a12a45 100644
--- a/OpenSim/Framework/PrimitiveBaseShape.cs
+++ b/OpenSim/Framework/PrimitiveBaseShape.cs
@@ -105,6 +105,7 @@ namespace OpenSim.Framework
105 private ushort _profileHollow; 105 private ushort _profileHollow;
106 private Vector3 _scale; 106 private Vector3 _scale;
107 private byte _state; 107 private byte _state;
108 private byte _lastattach;
108 private ProfileShape _profileShape; 109 private ProfileShape _profileShape;
109 private HollowShape _hollowShape; 110 private HollowShape _hollowShape;
110 111
@@ -207,6 +208,7 @@ namespace OpenSim.Framework
207 PCode = (byte)prim.PrimData.PCode; 208 PCode = (byte)prim.PrimData.PCode;
208 209
209 State = prim.PrimData.State; 210 State = prim.PrimData.State;
211 LastAttachPoint = prim.PrimData.State;
210 PathBegin = Primitive.PackBeginCut(prim.PrimData.PathBegin); 212 PathBegin = Primitive.PackBeginCut(prim.PrimData.PathBegin);
211 PathEnd = Primitive.PackEndCut(prim.PrimData.PathEnd); 213 PathEnd = Primitive.PackEndCut(prim.PrimData.PathEnd);
212 PathScaleX = Primitive.PackPathScale(prim.PrimData.PathScaleX); 214 PathScaleX = Primitive.PackPathScale(prim.PrimData.PathScaleX);
@@ -583,6 +585,15 @@ namespace OpenSim.Framework
583 } 585 }
584 } 586 }
585 587
588 public byte LastAttachPoint {
589 get {
590 return _lastattach;
591 }
592 set {
593 _lastattach = value;
594 }
595 }
596
586 public ProfileShape ProfileShape { 597 public ProfileShape ProfileShape {
587 get { 598 get {
588 return _profileShape; 599 return _profileShape;
diff --git a/OpenSim/Framework/RegionFlags.cs b/OpenSim/Framework/RegionFlags.cs
index a3089b0..7c6569e 100644
--- a/OpenSim/Framework/RegionFlags.cs
+++ b/OpenSim/Framework/RegionFlags.cs
@@ -48,6 +48,7 @@ namespace OpenSim.Framework
48 NoMove = 64, // Don't allow moving this region 48 NoMove = 64, // Don't allow moving this region
49 Reservation = 128, // This is an inactive reservation 49 Reservation = 128, // This is an inactive reservation
50 Authenticate = 256, // Require authentication 50 Authenticate = 256, // Require authentication
51 Hyperlink = 512 // Record represents a HG link 51 Hyperlink = 512, // Record represents a HG link
52 DefaultHGRegion = 1024 // Record represents a default region for hypergrid teleports only.
52 } 53 }
53} \ No newline at end of file 54} \ No newline at end of file
diff --git a/OpenSim/Framework/RegionInfo.cs b/OpenSim/Framework/RegionInfo.cs
index 24ec181..ae2ff63 100644
--- a/OpenSim/Framework/RegionInfo.cs
+++ b/OpenSim/Framework/RegionInfo.cs
@@ -100,6 +100,7 @@ namespace OpenSim.Framework
100 public class RegionInfo 100 public class RegionInfo
101 { 101 {
102 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 102 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
103 private static readonly string LogHeader = "[REGION INFO]";
103 104
104 public bool commFailTF = false; 105 public bool commFailTF = false;
105 public ConfigurationMember configMember; 106 public ConfigurationMember configMember;
@@ -139,16 +140,20 @@ namespace OpenSim.Framework
139 public bool m_allow_alternate_ports; 140 public bool m_allow_alternate_ports;
140 protected string m_externalHostName; 141 protected string m_externalHostName;
141 protected IPEndPoint m_internalEndPoint; 142 protected IPEndPoint m_internalEndPoint;
142 protected uint? m_regionLocX;
143 protected uint? m_regionLocY;
144 protected uint m_remotingPort; 143 protected uint m_remotingPort;
145 public UUID RegionID = UUID.Zero; 144 public UUID RegionID = UUID.Zero;
146 public string RemotingAddress; 145 public string RemotingAddress;
147 public UUID ScopeID = UUID.Zero; 146 public UUID ScopeID = UUID.Zero;
148 private UUID m_maptileStaticUUID = UUID.Zero; 147 private UUID m_maptileStaticUUID = UUID.Zero;
149 148
150 private Dictionary<String, String> m_otherSettings = new Dictionary<string, string>(); 149 public uint WorldLocX = 0;
150 public uint WorldLocY = 0;
151 public uint WorldLocZ = 0;
152 public uint RegionSizeX = Constants.RegionSize;
153 public uint RegionSizeY = Constants.RegionSize;
154 public uint RegionSizeZ = Constants.RegionHeight;
151 155
156 private Dictionary<String, String> m_otherSettings = new Dictionary<string, string>();
152 157
153 // Apparently, we're applying the same estatesettings regardless of whether it's local or remote. 158 // Apparently, we're applying the same estatesettings regardless of whether it's local or remote.
154 159
@@ -233,11 +238,12 @@ namespace OpenSim.Framework
233 m_serverURI = string.Empty; 238 m_serverURI = string.Empty;
234 } 239 }
235 240
236 public RegionInfo(uint regionLocX, uint regionLocY, IPEndPoint internalEndPoint, string externalUri) 241 public RegionInfo(uint legacyRegionLocX, uint legacyRegionLocY, IPEndPoint internalEndPoint, string externalUri)
237 { 242 {
238 m_regionLocX = regionLocX; 243 RegionLocX = legacyRegionLocX;
239 m_regionLocY = regionLocY; 244 RegionLocY = legacyRegionLocY;
240 245 RegionSizeX = Constants.RegionSize;
246 RegionSizeY = Constants.RegionSize;
241 m_internalEndPoint = internalEndPoint; 247 m_internalEndPoint = internalEndPoint;
242 m_externalHostName = externalUri; 248 m_externalHostName = externalUri;
243 m_serverURI = string.Empty; 249 m_serverURI = string.Empty;
@@ -451,25 +457,42 @@ namespace OpenSim.Framework
451 457
452 /// <summary> 458 /// <summary>
453 /// The x co-ordinate of this region in map tiles (e.g. 1000). 459 /// The x co-ordinate of this region in map tiles (e.g. 1000).
460 /// Coordinate is scaled as world coordinates divided by the legacy region size
461 /// and is thus is the number of legacy regions.
454 /// </summary> 462 /// </summary>
455 public uint RegionLocX 463 public uint RegionLocX
456 { 464 {
457 get { return m_regionLocX.Value; } 465 get { return WorldLocX / Constants.RegionSize; }
458 set { m_regionLocX = value; } 466 set { WorldLocX = value * Constants.RegionSize; }
459 } 467 }
460 468
461 /// <summary> 469 /// <summary>
462 /// The y co-ordinate of this region in map tiles (e.g. 1000). 470 /// The y co-ordinate of this region in map tiles (e.g. 1000).
471 /// Coordinate is scaled as world coordinates divided by the legacy region size
472 /// and is thus is the number of legacy regions.
463 /// </summary> 473 /// </summary>
464 public uint RegionLocY 474 public uint RegionLocY
465 { 475 {
466 get { return m_regionLocY.Value; } 476 get { return WorldLocY / Constants.RegionSize; }
467 set { m_regionLocY = value; } 477 set { WorldLocY = value * Constants.RegionSize; }
468 } 478 }
469 479
480 public void SetDefaultRegionSize()
481 {
482 WorldLocX = 0;
483 WorldLocY = 0;
484 WorldLocZ = 0;
485 RegionSizeX = Constants.RegionSize;
486 RegionSizeY = Constants.RegionSize;
487 RegionSizeZ = Constants.RegionHeight;
488 }
489
490 // A unique region handle is created from the region's world coordinates.
491 // This cannot be changed because some code expects to receive the region handle and then
492 // compute the region coordinates from it.
470 public ulong RegionHandle 493 public ulong RegionHandle
471 { 494 {
472 get { return Util.UIntsToLong((RegionLocX * (uint) Constants.RegionSize), (RegionLocY * (uint) Constants.RegionSize)); } 495 get { return Util.UIntsToLong(WorldLocX, WorldLocY); }
473 } 496 }
474 497
475 public void SetEndPoint(string ipaddr, int port) 498 public void SetEndPoint(string ipaddr, int port)
@@ -576,8 +599,25 @@ namespace OpenSim.Framework
576 599
577 string[] locationElements = location.Split(new char[] {','}); 600 string[] locationElements = location.Split(new char[] {','});
578 601
579 m_regionLocX = Convert.ToUInt32(locationElements[0]); 602 RegionLocX = Convert.ToUInt32(locationElements[0]);
580 m_regionLocY = Convert.ToUInt32(locationElements[1]); 603 RegionLocY = Convert.ToUInt32(locationElements[1]);
604
605 // Region size
606 // Default to legacy region size if not specified.
607 allKeys.Remove("SizeX");
608 string configSizeX = config.GetString("SizeX", Constants.RegionSize.ToString());
609 config.Set("SizeX", configSizeX);
610 RegionSizeX = Convert.ToUInt32(configSizeX);
611 allKeys.Remove("SizeY");
612 string configSizeY = config.GetString("SizeY", Constants.RegionSize.ToString());
613 config.Set("SizeY", configSizeX);
614 RegionSizeY = Convert.ToUInt32(configSizeY);
615 allKeys.Remove("SizeZ");
616 string configSizeZ = config.GetString("SizeZ", Constants.RegionHeight.ToString());
617 config.Set("SizeZ", configSizeX);
618 RegionSizeZ = Convert.ToUInt32(configSizeZ);
619
620 DoRegionSizeSanityChecks();
581 621
582 // InternalAddress 622 // InternalAddress
583 // 623 //
@@ -697,6 +737,57 @@ namespace OpenSim.Framework
697 } 737 }
698 } 738 }
699 739
740 // Make sure user specified region sizes are sane.
741 // Must be multiples of legacy region size (256).
742 private void DoRegionSizeSanityChecks()
743 {
744 if (RegionSizeX != Constants.RegionSize || RegionSizeY != Constants.RegionSize)
745 {
746 // Doing non-legacy region sizes.
747 // Enforce region size to be multiples of the legacy region size (256)
748 uint partial = RegionSizeX % Constants.RegionSize;
749 if (partial != 0)
750 {
751 RegionSizeX -= partial;
752 if (RegionSizeX == 0)
753 RegionSizeX = Constants.RegionSize;
754 m_log.ErrorFormat("{0} Region size must be multiple of {1}. Enforcing {2}.RegionSizeX={3} instead of specified {4}",
755 LogHeader, Constants.RegionSize, m_regionName, RegionSizeX, RegionSizeX + partial);
756 }
757 partial = RegionSizeY % Constants.RegionSize;
758 if (partial != 0)
759 {
760 RegionSizeY -= partial;
761 if (RegionSizeY == 0)
762 RegionSizeY = Constants.RegionSize;
763 m_log.ErrorFormat("{0} Region size must be multiple of {1}. Enforcing {2}.RegionSizeY={3} instead of specified {4}",
764 LogHeader, Constants.RegionSize, m_regionName, RegionSizeY, RegionSizeY + partial);
765 }
766
767 // Because of things in the viewer, regions MUST be square.
768 // Remove this check when viewers have been updated.
769 if (RegionSizeX != RegionSizeY)
770 {
771 uint minSize = Math.Min(RegionSizeX, RegionSizeY);
772 RegionSizeX = minSize;
773 RegionSizeY = minSize;
774 m_log.ErrorFormat("{0} Regions must be square until viewers are updated. Forcing region {1} size to <{2},{3}>",
775 LogHeader, m_regionName, RegionSizeX, RegionSizeY);
776 }
777
778 // There is a practical limit to region size.
779 if (RegionSizeX > Constants.MaximumRegionSize || RegionSizeY > Constants.MaximumRegionSize)
780 {
781 RegionSizeX = Util.Clamp<uint>(RegionSizeX, Constants.RegionSize, Constants.MaximumRegionSize);
782 RegionSizeY = Util.Clamp<uint>(RegionSizeY, Constants.RegionSize, Constants.MaximumRegionSize);
783 m_log.ErrorFormat("{0} Region dimensions must be less than {1}. Clamping {2}'s size to <{3},{4}>",
784 LogHeader, Constants.MaximumRegionSize, m_regionName, RegionSizeX, RegionSizeY);
785 }
786
787 m_log.InfoFormat("{0} Region {1} size set to <{2},{3}>", LogHeader, m_regionName, RegionSizeX, RegionSizeY);
788 }
789 }
790
700 private void WriteNiniConfig(IConfigSource source) 791 private void WriteNiniConfig(IConfigSource source)
701 { 792 {
702 IConfig config = source.Configs[RegionName]; 793 IConfig config = source.Configs[RegionName];
@@ -708,11 +799,17 @@ namespace OpenSim.Framework
708 799
709 config.Set("RegionUUID", RegionID.ToString()); 800 config.Set("RegionUUID", RegionID.ToString());
710 801
711 string location = String.Format("{0},{1}", m_regionLocX, m_regionLocY); 802 string location = String.Format("{0},{1}", RegionLocX, RegionLocY);
712 config.Set("Location", location); 803 config.Set("Location", location);
713 804
714 if (DataStore != String.Empty) 805 if (DataStore != String.Empty)
715 config.Set("Datastore", DataStore); 806 config.Set("Datastore", DataStore);
807 if (RegionSizeX != Constants.RegionSize || RegionSizeY != Constants.RegionSize)
808 {
809 config.Set("SizeX", RegionSizeX);
810 config.Set("SizeY", RegionSizeY);
811 config.Set("SizeZ", RegionSizeZ);
812 }
716 813
717 config.Set("InternalAddress", m_internalEndPoint.Address.ToString()); 814 config.Set("InternalAddress", m_internalEndPoint.Address.ToString());
718 config.Set("InternalPort", m_internalEndPoint.Port); 815 config.Set("InternalPort", m_internalEndPoint.Port);
@@ -796,10 +893,18 @@ namespace OpenSim.Framework
796 RegionID.ToString(), true); 893 RegionID.ToString(), true);
797 configMember.addConfigurationOption("sim_name", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY, 894 configMember.addConfigurationOption("sim_name", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY,
798 "Region Name", RegionName, true); 895 "Region Name", RegionName, true);
896
799 configMember.addConfigurationOption("sim_location_x", ConfigurationOption.ConfigurationTypes.TYPE_UINT32, 897 configMember.addConfigurationOption("sim_location_x", ConfigurationOption.ConfigurationTypes.TYPE_UINT32,
800 "Grid Location (X Axis)", m_regionLocX.ToString(), true); 898 "Grid Location (X Axis)", RegionLocX.ToString(), true);
801 configMember.addConfigurationOption("sim_location_y", ConfigurationOption.ConfigurationTypes.TYPE_UINT32, 899 configMember.addConfigurationOption("sim_location_y", ConfigurationOption.ConfigurationTypes.TYPE_UINT32,
802 "Grid Location (Y Axis)", m_regionLocY.ToString(), true); 900 "Grid Location (Y Axis)", RegionLocY.ToString(), true);
901 configMember.addConfigurationOption("sim_size_x", ConfigurationOption.ConfigurationTypes.TYPE_UINT32,
902 "Size of region in X dimension", RegionSizeX.ToString(), true);
903 configMember.addConfigurationOption("sim_size_y", ConfigurationOption.ConfigurationTypes.TYPE_UINT32,
904 "Size of region in Y dimension", RegionSizeY.ToString(), true);
905 configMember.addConfigurationOption("sim_size_z", ConfigurationOption.ConfigurationTypes.TYPE_UINT32,
906 "Size of region in Z dimension", RegionSizeZ.ToString(), true);
907
803 //m_configMember.addConfigurationOption("datastore", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY, "Filename for local storage", "OpenSim.db", false); 908 //m_configMember.addConfigurationOption("datastore", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY, "Filename for local storage", "OpenSim.db", false);
804 configMember.addConfigurationOption("internal_ip_address", 909 configMember.addConfigurationOption("internal_ip_address",
805 ConfigurationOption.ConfigurationTypes.TYPE_IP_ADDRESS, 910 ConfigurationOption.ConfigurationTypes.TYPE_IP_ADDRESS,
@@ -862,10 +967,18 @@ namespace OpenSim.Framework
862 UUID.Random().ToString(), true); 967 UUID.Random().ToString(), true);
863 configMember.addConfigurationOption("sim_name", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY, 968 configMember.addConfigurationOption("sim_name", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY,
864 "Region Name", "OpenSim Test", false); 969 "Region Name", "OpenSim Test", false);
970
865 configMember.addConfigurationOption("sim_location_x", ConfigurationOption.ConfigurationTypes.TYPE_UINT32, 971 configMember.addConfigurationOption("sim_location_x", ConfigurationOption.ConfigurationTypes.TYPE_UINT32,
866 "Grid Location (X Axis)", "1000", false); 972 "Grid Location (X Axis)", "1000", false);
867 configMember.addConfigurationOption("sim_location_y", ConfigurationOption.ConfigurationTypes.TYPE_UINT32, 973 configMember.addConfigurationOption("sim_location_y", ConfigurationOption.ConfigurationTypes.TYPE_UINT32,
868 "Grid Location (Y Axis)", "1000", false); 974 "Grid Location (Y Axis)", "1000", false);
975 configMember.addConfigurationOption("sim_size_x", ConfigurationOption.ConfigurationTypes.TYPE_UINT32,
976 "Size of region in X dimension", Constants.RegionSize.ToString(), false);
977 configMember.addConfigurationOption("sim_size_y", ConfigurationOption.ConfigurationTypes.TYPE_UINT32,
978 "Size of region in Y dimension", Constants.RegionSize.ToString(), false);
979 configMember.addConfigurationOption("sim_size_z", ConfigurationOption.ConfigurationTypes.TYPE_UINT32,
980 "Size of region in Z dimension", Constants.RegionHeight.ToString(), false);
981
869 //m_configMember.addConfigurationOption("datastore", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY, "Filename for local storage", "OpenSim.db", false); 982 //m_configMember.addConfigurationOption("datastore", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY, "Filename for local storage", "OpenSim.db", false);
870 configMember.addConfigurationOption("internal_ip_address", 983 configMember.addConfigurationOption("internal_ip_address",
871 ConfigurationOption.ConfigurationTypes.TYPE_IP_ADDRESS, 984 ConfigurationOption.ConfigurationTypes.TYPE_IP_ADDRESS,
@@ -923,10 +1036,19 @@ namespace OpenSim.Framework
923 RegionName = (string) configuration_result; 1036 RegionName = (string) configuration_result;
924 break; 1037 break;
925 case "sim_location_x": 1038 case "sim_location_x":
926 m_regionLocX = (uint) configuration_result; 1039 RegionLocX = (uint) configuration_result;
927 break; 1040 break;
928 case "sim_location_y": 1041 case "sim_location_y":
929 m_regionLocY = (uint) configuration_result; 1042 RegionLocY = (uint) configuration_result;
1043 break;
1044 case "sim_size_x":
1045 RegionSizeX = (uint) configuration_result;
1046 break;
1047 case "sim_size_y":
1048 RegionSizeY = (uint) configuration_result;
1049 break;
1050 case "sim_size_z":
1051 RegionSizeZ = (uint) configuration_result;
930 break; 1052 break;
931 case "datastore": 1053 case "datastore":
932 DataStore = (string) configuration_result; 1054 DataStore = (string) configuration_result;
@@ -1010,8 +1132,13 @@ namespace OpenSim.Framework
1010 args["external_host_name"] = OSD.FromString(ExternalHostName); 1132 args["external_host_name"] = OSD.FromString(ExternalHostName);
1011 args["http_port"] = OSD.FromString(HttpPort.ToString()); 1133 args["http_port"] = OSD.FromString(HttpPort.ToString());
1012 args["server_uri"] = OSD.FromString(ServerURI); 1134 args["server_uri"] = OSD.FromString(ServerURI);
1135
1013 args["region_xloc"] = OSD.FromString(RegionLocX.ToString()); 1136 args["region_xloc"] = OSD.FromString(RegionLocX.ToString());
1014 args["region_yloc"] = OSD.FromString(RegionLocY.ToString()); 1137 args["region_yloc"] = OSD.FromString(RegionLocY.ToString());
1138 args["region_size_x"] = OSD.FromString(RegionSizeX.ToString());
1139 args["region_size_y"] = OSD.FromString(RegionSizeY.ToString());
1140 args["region_size_z"] = OSD.FromString(RegionSizeZ.ToString());
1141
1015 args["internal_ep_address"] = OSD.FromString(InternalEndPoint.Address.ToString()); 1142 args["internal_ep_address"] = OSD.FromString(InternalEndPoint.Address.ToString());
1016 args["internal_ep_port"] = OSD.FromString(InternalEndPoint.Port.ToString()); 1143 args["internal_ep_port"] = OSD.FromString(InternalEndPoint.Port.ToString());
1017 if ((RemotingAddress != null) && !RemotingAddress.Equals("")) 1144 if ((RemotingAddress != null) && !RemotingAddress.Equals(""))
@@ -1050,6 +1177,13 @@ namespace OpenSim.Framework
1050 UInt32.TryParse(args["region_yloc"].AsString(), out locy); 1177 UInt32.TryParse(args["region_yloc"].AsString(), out locy);
1051 RegionLocY = locy; 1178 RegionLocY = locy;
1052 } 1179 }
1180 if (args.ContainsKey("region_size_x"))
1181 RegionSizeX = (uint)args["region_size_x"].AsInteger();
1182 if (args.ContainsKey("region_size_y"))
1183 RegionSizeY = (uint)args["region_size_y"].AsInteger();
1184 if (args.ContainsKey("region_size_z"))
1185 RegionSizeZ = (uint)args["region_size_z"].AsInteger();
1186
1053 IPAddress ip_addr = null; 1187 IPAddress ip_addr = null;
1054 if (args["internal_ep_address"] != null) 1188 if (args["internal_ep_address"] != null)
1055 { 1189 {
diff --git a/OpenSim/Framework/RegionLoader/Filesystem/Properties/AssemblyInfo.cs b/OpenSim/Framework/RegionLoader/Filesystem/Properties/AssemblyInfo.cs
index d4806f1..563bcb9 100644
--- a/OpenSim/Framework/RegionLoader/Filesystem/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/RegionLoader/Filesystem/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Framework/RegionLoader/Web/Properties/AssemblyInfo.cs b/OpenSim/Framework/RegionLoader/Web/Properties/AssemblyInfo.cs
index 1541a5b..ab36f10 100644
--- a/OpenSim/Framework/RegionLoader/Web/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/RegionLoader/Web/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Framework/RegionSettings.cs b/OpenSim/Framework/RegionSettings.cs
index 47a2780..dec01ea 100644
--- a/OpenSim/Framework/RegionSettings.cs
+++ b/OpenSim/Framework/RegionSettings.cs
@@ -200,7 +200,7 @@ namespace OpenSim.Framework
200 set { m_ObjectBonus = value; } 200 set { m_ObjectBonus = value; }
201 } 201 }
202 202
203 private int m_Maturity = 1; 203 private int m_Maturity = 0;
204 204
205 public int Maturity 205 public int Maturity
206 { 206 {
@@ -504,21 +504,14 @@ namespace OpenSim.Framework
504 set { m_TelehubEnabled = value; } 504 set { m_TelehubEnabled = value; }
505 } 505 }
506 506
507 // Connected Telehub object 507 /// <summary>
508 private UUID m_TelehubObject = UUID.Zero; 508 /// Connected Telehub object
509 public UUID TelehubObject 509 /// </summary>
510 { 510 public UUID TelehubObject { get; set; }
511 get
512 {
513 return m_TelehubObject;
514 }
515 set
516 {
517 m_TelehubObject = value;
518 }
519 }
520 511
521 // Our Connected Telehub's SpawnPoints 512 /// <summary>
513 /// Our connected Telehub's SpawnPoints
514 /// </summary>
522 public List<SpawnPoint> l_SpawnPoints = new List<SpawnPoint>(); 515 public List<SpawnPoint> l_SpawnPoints = new List<SpawnPoint>();
523 516
524 // Add a SpawnPoint 517 // Add a SpawnPoint
@@ -549,4 +542,4 @@ namespace OpenSim.Framework
549 l_SpawnPoints.Clear(); 542 l_SpawnPoints.Clear();
550 } 543 }
551 } 544 }
552} \ No newline at end of file 545}
diff --git a/OpenSim/Framework/SLUtil.cs b/OpenSim/Framework/SLUtil.cs
index 537de7a..9249105 100644
--- a/OpenSim/Framework/SLUtil.cs
+++ b/OpenSim/Framework/SLUtil.cs
@@ -39,8 +39,32 @@ namespace OpenSim.Framework
39 { 39 {
40// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 40// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
41 41
42 /// <summary>
43 /// Asset types used only in OpenSim.
44 /// To avoid clashing with the code numbers used in Second Life, use only negative numbers here.
45 /// </summary>
46 public enum OpenSimAssetType : sbyte
47 {
48 Material = -2
49 }
50
51
42 #region SL / file extension / content-type conversions 52 #region SL / file extension / content-type conversions
43 53
54 /// <summary>
55 /// Returns the Enum entry corresponding to the given code, regardless of whether it belongs
56 /// to the AssetType or OpenSimAssetType enums.
57 /// </summary>
58 public static object AssetTypeFromCode(sbyte assetType)
59 {
60 if (Enum.IsDefined(typeof(OpenMetaverse.AssetType), assetType))
61 return (OpenMetaverse.AssetType)assetType;
62 else if (Enum.IsDefined(typeof(OpenSimAssetType), assetType))
63 return (OpenSimAssetType)assetType;
64 else
65 return OpenMetaverse.AssetType.Unknown;
66 }
67
44 private class TypeMapping 68 private class TypeMapping
45 { 69 {
46 private sbyte assetType; 70 private sbyte assetType;
@@ -56,12 +80,7 @@ namespace OpenSim.Framework
56 80
57 public object AssetType 81 public object AssetType
58 { 82 {
59 get { 83 get { return AssetTypeFromCode(assetType); }
60 if (Enum.IsDefined(typeof(OpenMetaverse.AssetType), assetType))
61 return (OpenMetaverse.AssetType)assetType;
62 else
63 return OpenMetaverse.AssetType.Unknown;
64 }
65 } 84 }
66 85
67 public InventoryType InventoryType 86 public InventoryType InventoryType
@@ -102,6 +121,11 @@ namespace OpenSim.Framework
102 : this((sbyte)assetType, inventoryType, contentType, null, extension) 121 : this((sbyte)assetType, inventoryType, contentType, null, extension)
103 { 122 {
104 } 123 }
124
125 public TypeMapping(OpenSimAssetType assetType, InventoryType inventoryType, string contentType, string extension)
126 : this((sbyte)assetType, inventoryType, contentType, null, extension)
127 {
128 }
105 } 129 }
106 130
107 /// <summary> 131 /// <summary>
@@ -142,7 +166,9 @@ namespace OpenSim.Framework
142 new TypeMapping(AssetType.CurrentOutfitFolder, InventoryType.Unknown, "application/vnd.ll.currentoutfitfolder", "currentoutfitfolder"), 166 new TypeMapping(AssetType.CurrentOutfitFolder, InventoryType.Unknown, "application/vnd.ll.currentoutfitfolder", "currentoutfitfolder"),
143 new TypeMapping(AssetType.OutfitFolder, InventoryType.Unknown, "application/vnd.ll.outfitfolder", "outfitfolder"), 167 new TypeMapping(AssetType.OutfitFolder, InventoryType.Unknown, "application/vnd.ll.outfitfolder", "outfitfolder"),
144 new TypeMapping(AssetType.MyOutfitsFolder, InventoryType.Unknown, "application/vnd.ll.myoutfitsfolder", "myoutfitsfolder"), 168 new TypeMapping(AssetType.MyOutfitsFolder, InventoryType.Unknown, "application/vnd.ll.myoutfitsfolder", "myoutfitsfolder"),
145 new TypeMapping(AssetType.Mesh, InventoryType.Mesh, "application/vnd.ll.mesh", "llm") 169 new TypeMapping(AssetType.Mesh, InventoryType.Mesh, "application/vnd.ll.mesh", "llm"),
170
171 new TypeMapping(OpenSimAssetType.Material, InventoryType.Unknown, "application/llsd+xml", "material")
146 }; 172 };
147 173
148 private static Dictionary<sbyte, string> asset2Content; 174 private static Dictionary<sbyte, string> asset2Content;
@@ -247,12 +273,18 @@ namespace OpenSim.Framework
247 /// <returns></returns> 273 /// <returns></returns>
248 public static List<string> ParseNotecardToList(string rawInput) 274 public static List<string> ParseNotecardToList(string rawInput)
249 { 275 {
250 string[] input = rawInput.Replace("\r", "").Split('\n'); 276 string[] input;
251 int idx = 0; 277 int idx = 0;
252 int level = 0; 278 int level = 0;
253 List<string> output = new List<string>(); 279 List<string> output = new List<string>();
254 string[] words; 280 string[] words;
255 281
282 //The Linden format always ends with a } after the input data.
283 //Strip off trailing } so there is nothing after the input data.
284 int i = rawInput.LastIndexOf("}");
285 rawInput = rawInput.Remove(i, rawInput.Length-i);
286 input = rawInput.Replace("\r", "").Split('\n');
287
256 while (idx < input.Length) 288 while (idx < input.Length)
257 { 289 {
258 if (input[idx] == "{") 290 if (input[idx] == "{")
@@ -287,24 +319,18 @@ namespace OpenSim.Framework
287 break; 319 break;
288 if (words[0] == "Text") 320 if (words[0] == "Text")
289 { 321 {
290 int len = int.Parse(words[2]); 322 idx++; //Now points to first line of notecard text
291 idx++;
292 323
293 int count = -1; 324 //Number of lines in notecard.
325 int lines = input.Length - idx;
326 int line = 0;
294 327
295 while (count < len && idx < input.Length) 328 while (line < lines)
296 { 329 {
297 // int l = input[idx].Length; 330// m_log.DebugFormat("[PARSE NOTECARD]: Adding line {0}", input[idx]);
298 string ln = input[idx]; 331 output.Add(input[idx]);
299
300 int need = len-count-1;
301 if (ln.Length > need)
302 ln = ln.Substring(0, need);
303
304// m_log.DebugFormat("[PARSE NOTECARD]: Adding line {0}", ln);
305 output.Add(ln);
306 count += ln.Length + 1;
307 idx++; 332 idx++;
333 line++;
308 } 334 }
309 335
310 return output; 336 return output;
diff --git a/OpenSim/Framework/Serialization/ArchiveConstants.cs b/OpenSim/Framework/Serialization/ArchiveConstants.cs
index 0c12787..73ebfae 100644
--- a/OpenSim/Framework/Serialization/ArchiveConstants.cs
+++ b/OpenSim/Framework/Serialization/ArchiveConstants.cs
@@ -29,6 +29,7 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Text; 30using System.Text;
31using OpenMetaverse; 31using OpenMetaverse;
32using OpenSimAssetType = OpenSim.Framework.SLUtil.OpenSimAssetType;
32 33
33namespace OpenSim.Framework.Serialization 34namespace OpenSim.Framework.Serialization
34{ 35{
@@ -128,6 +129,7 @@ namespace OpenSim.Framework.Serialization
128 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Texture] = ASSET_EXTENSION_SEPARATOR + "texture.jp2"; 129 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Texture] = ASSET_EXTENSION_SEPARATOR + "texture.jp2";
129 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.TextureTGA] = ASSET_EXTENSION_SEPARATOR + "texture.tga"; 130 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.TextureTGA] = ASSET_EXTENSION_SEPARATOR + "texture.tga";
130 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.TrashFolder] = ASSET_EXTENSION_SEPARATOR + "trashfolder.txt"; // Not sure if we'll ever see this 131 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.TrashFolder] = ASSET_EXTENSION_SEPARATOR + "trashfolder.txt"; // Not sure if we'll ever see this
132 ASSET_TYPE_TO_EXTENSION[(sbyte)OpenSimAssetType.Material] = ASSET_EXTENSION_SEPARATOR + "material.xml"; // Not sure if we'll ever see this
131 133
132 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "animation.bvh"] = (sbyte)AssetType.Animation; 134 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "animation.bvh"] = (sbyte)AssetType.Animation;
133 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "bodypart.txt"] = (sbyte)AssetType.Bodypart; 135 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "bodypart.txt"] = (sbyte)AssetType.Bodypart;
@@ -152,6 +154,7 @@ namespace OpenSim.Framework.Serialization
152 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "texture.jp2"] = (sbyte)AssetType.Texture; 154 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "texture.jp2"] = (sbyte)AssetType.Texture;
153 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "texture.tga"] = (sbyte)AssetType.TextureTGA; 155 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "texture.tga"] = (sbyte)AssetType.TextureTGA;
154 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "trashfolder.txt"] = (sbyte)AssetType.TrashFolder; 156 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "trashfolder.txt"] = (sbyte)AssetType.TrashFolder;
157 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "material.xml"] = (sbyte)OpenSimAssetType.Material;
155 } 158 }
156 159
157 public static string CreateOarLandDataPath(LandData ld) 160 public static string CreateOarLandDataPath(LandData ld)
diff --git a/OpenSim/Framework/Serialization/External/UserInventoryItemSerializer.cs b/OpenSim/Framework/Serialization/External/UserInventoryItemSerializer.cs
index 88f9581..f2a6b8b 100644
--- a/OpenSim/Framework/Serialization/External/UserInventoryItemSerializer.cs
+++ b/OpenSim/Framework/Serialization/External/UserInventoryItemSerializer.cs
@@ -277,7 +277,7 @@ namespace OpenSim.Framework.Serialization.External
277 writer.WriteStartElement("GroupOwned"); 277 writer.WriteStartElement("GroupOwned");
278 writer.WriteString(inventoryItem.GroupOwned.ToString()); 278 writer.WriteString(inventoryItem.GroupOwned.ToString());
279 writer.WriteEndElement(); 279 writer.WriteEndElement();
280 if (options.ContainsKey("creators") && inventoryItem.CreatorData != null && inventoryItem.CreatorData != string.Empty) 280 if (options.ContainsKey("creators") && !string.IsNullOrEmpty(inventoryItem.CreatorData))
281 writer.WriteElementString("CreatorData", inventoryItem.CreatorData); 281 writer.WriteElementString("CreatorData", inventoryItem.CreatorData);
282 else if (options.ContainsKey("home")) 282 else if (options.ContainsKey("home"))
283 { 283 {
diff --git a/OpenSim/Framework/Serialization/Properties/AssemblyInfo.cs b/OpenSim/Framework/Serialization/Properties/AssemblyInfo.cs
index a8dff93..3f04148 100644
--- a/OpenSim/Framework/Serialization/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/Serialization/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Framework/Servers/BaseOpenSimServer.cs b/OpenSim/Framework/Servers/BaseOpenSimServer.cs
index 6c04c69..cbd34a2 100644
--- a/OpenSim/Framework/Servers/BaseOpenSimServer.cs
+++ b/OpenSim/Framework/Servers/BaseOpenSimServer.cs
@@ -86,26 +86,23 @@ namespace OpenSim.Framework.Servers
86 /// </summary> 86 /// </summary>
87 protected virtual void StartupSpecific() 87 protected virtual void StartupSpecific()
88 { 88 {
89 if (m_console == null) 89 StatsManager.SimExtraStats = new SimExtraStatsCollector();
90 return;
91
92 RegisterCommonCommands(); 90 RegisterCommonCommands();
93 91 RegisterCommonComponents(Config);
94 m_console.Commands.AddCommand("General", false, "quit", 92 }
95 "quit", 93
96 "Quit the application", HandleQuit); 94 protected override void ShutdownSpecific()
95 {
96 m_log.Info("[SHUTDOWN]: Shutdown processing on main thread complete. Exiting...");
97
98 RemovePIDFile();
97 99
98 m_console.Commands.AddCommand("General", false, "shutdown", 100 base.ShutdownSpecific();
99 "shutdown", 101
100 "Quit the application", HandleQuit); 102 Environment.Exit(0);
101 } 103 }
102 104
103 /// <summary> 105 /// <summary>
104 /// Should be overriden and referenced by descendents if they need to perform extra shutdown processing
105 /// </summary>
106 public virtual void ShutdownSpecific() {}
107
108 /// <summary>
109 /// Provides a list of help topics that are available. Overriding classes should append their topics to the 106 /// Provides a list of help topics that are available. Overriding classes should append their topics to the
110 /// information returned when the base method is called. 107 /// information returned when the base method is called.
111 /// </summary> 108 /// </summary>
@@ -148,30 +145,13 @@ namespace OpenSim.Framework.Servers
148 145
149 TimeSpan timeTaken = DateTime.Now - m_startuptime; 146 TimeSpan timeTaken = DateTime.Now - m_startuptime;
150 147
151 m_log.InfoFormat( 148 MainConsole.Instance.OutputFormat(
152 "[STARTUP]: Non-script portion of startup took {0}m {1}s. PLEASE WAIT FOR LOGINS TO BE ENABLED ON REGIONS ONCE SCRIPTS HAVE STARTED.", 149 "PLEASE WAIT FOR LOGINS TO BE ENABLED ON REGIONS ONCE SCRIPTS HAVE STARTED. Non-script portion of startup took {0}m {1}s.",
153 timeTaken.Minutes, timeTaken.Seconds); 150 timeTaken.Minutes, timeTaken.Seconds);
154 } 151 }
155 152
156 /// <summary> 153 public string osSecret
157 /// Should be overriden and referenced by descendents if they need to perform extra shutdown processing
158 /// </summary>
159 public virtual void Shutdown()
160 { 154 {
161 ShutdownSpecific();
162
163 m_log.Info("[SHUTDOWN]: Shutdown processing on main thread complete. Exiting...");
164 RemovePIDFile();
165
166 Environment.Exit(0);
167 }
168
169 private void HandleQuit(string module, string[] args)
170 {
171 Shutdown();
172 }
173
174 public string osSecret {
175 // Secret uuid for the simulator 155 // Secret uuid for the simulator
176 get { return m_osSecret; } 156 get { return m_osSecret; }
177 } 157 }
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
index 97035e3..7841f47 100644
--- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
+++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
@@ -54,7 +54,6 @@ namespace OpenSim.Framework.Servers.HttpServer
54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55 private HttpServerLogWriter httpserverlog = new HttpServerLogWriter(); 55 private HttpServerLogWriter httpserverlog = new HttpServerLogWriter();
56 56
57
58 /// <summary> 57 /// <summary>
59 /// This is a pending websocket request before it got an sucessful upgrade response. 58 /// This is a pending websocket request before it got an sucessful upgrade response.
60 /// The consumer must call handler.HandshakeAndUpgrade() to signal to the handler to 59 /// The consumer must call handler.HandshakeAndUpgrade() to signal to the handler to
@@ -81,6 +80,11 @@ namespace OpenSim.Framework.Servers.HttpServer
81 /// </remarks> 80 /// </remarks>
82 public int RequestNumber { get; private set; } 81 public int RequestNumber { get; private set; }
83 82
83 /// <summary>
84 /// Statistic for holding number of requests processed.
85 /// </summary>
86 private Stat m_requestsProcessedStat;
87
84 private volatile int NotSocketErrors = 0; 88 private volatile int NotSocketErrors = 0;
85 public volatile bool HTTPDRunning = false; 89 public volatile bool HTTPDRunning = false;
86 90
@@ -383,6 +387,8 @@ namespace OpenSim.Framework.Servers.HttpServer
383 387
384 if (TryGetPollServiceHTTPHandler(request.UriPath.ToString(), out psEvArgs)) 388 if (TryGetPollServiceHTTPHandler(request.UriPath.ToString(), out psEvArgs))
385 { 389 {
390 psEvArgs.RequestsReceived++;
391
386 PollServiceHttpRequest psreq = new PollServiceHttpRequest(psEvArgs, context, request); 392 PollServiceHttpRequest psreq = new PollServiceHttpRequest(psEvArgs, context, request);
387 393
388 if (psEvArgs.Request != null) 394 if (psEvArgs.Request != null)
@@ -437,9 +443,8 @@ namespace OpenSim.Framework.Servers.HttpServer
437 } 443 }
438 } 444 }
439 445
440 public void OnHandleRequestIOThread(IHttpClientContext context, IHttpRequest request) 446 private void OnHandleRequestIOThread(IHttpClientContext context, IHttpRequest request)
441 { 447 {
442
443 OSHttpRequest req = new OSHttpRequest(context, request); 448 OSHttpRequest req = new OSHttpRequest(context, request);
444 WebSocketRequestDelegate dWebSocketRequestDelegate = null; 449 WebSocketRequestDelegate dWebSocketRequestDelegate = null;
445 lock (m_WebSocketHandlers) 450 lock (m_WebSocketHandlers)
@@ -454,9 +459,8 @@ namespace OpenSim.Framework.Servers.HttpServer
454 } 459 }
455 460
456 OSHttpResponse resp = new OSHttpResponse(new HttpResponse(context, request),context); 461 OSHttpResponse resp = new OSHttpResponse(new HttpResponse(context, request),context);
457 462 resp.ReuseContext = true;
458 HandleRequest(req, resp); 463 HandleRequest(req, resp);
459
460 464
461 // !!!HACK ALERT!!! 465 // !!!HACK ALERT!!!
462 // There seems to be a bug in the underlying http code that makes subsequent requests 466 // There seems to be a bug in the underlying http code that makes subsequent requests
@@ -687,7 +691,7 @@ namespace OpenSim.Framework.Servers.HttpServer
687 691
688 if (buffer != null) 692 if (buffer != null)
689 { 693 {
690 if (!response.SendChunked) 694 if (!response.SendChunked && response.ContentLength64 <= 0)
691 response.ContentLength64 = buffer.LongLength; 695 response.ContentLength64 = buffer.LongLength;
692 696
693 response.OutputStream.Write(buffer, 0, buffer.Length); 697 response.OutputStream.Write(buffer, 0, buffer.Length);
@@ -782,7 +786,7 @@ namespace OpenSim.Framework.Servers.HttpServer
782 "[BASE HTTP SERVER]: HTTP IN {0} :{1} {2} content type handler {3} {4} from {5}", 786 "[BASE HTTP SERVER]: HTTP IN {0} :{1} {2} content type handler {3} {4} from {5}",
783 RequestNumber, 787 RequestNumber,
784 Port, 788 Port,
785 (request.ContentType == null || request.ContentType == "") ? "not set" : request.ContentType, 789 string.IsNullOrEmpty(request.ContentType) ? "not set" : request.ContentType,
786 request.HttpMethod, 790 request.HttpMethod,
787 request.Url.PathAndQuery, 791 request.Url.PathAndQuery,
788 request.RemoteIPEndPoint); 792 request.RemoteIPEndPoint);
@@ -1053,7 +1057,21 @@ namespace OpenSim.Framework.Servers.HttpServer
1053 } 1057 }
1054 1058
1055 response.ContentType = "text/xml"; 1059 response.ContentType = "text/xml";
1056 responseString = XmlRpcResponseSerializer.Singleton.Serialize(xmlRpcResponse); 1060 using (MemoryStream outs = new MemoryStream())
1061 {
1062 using (XmlTextWriter writer = new XmlTextWriter(outs, Encoding.UTF8))
1063 {
1064 writer.Formatting = Formatting.None;
1065 XmlRpcResponseSerializer.Singleton.Serialize(writer, xmlRpcResponse);
1066 writer.Flush();
1067 outs.Flush();
1068 outs.Position = 0;
1069 using (StreamReader sr = new StreamReader(outs))
1070 {
1071 responseString = sr.ReadToEnd();
1072 }
1073 }
1074 }
1057 } 1075 }
1058 else 1076 else
1059 { 1077 {
@@ -1850,8 +1868,8 @@ namespace OpenSim.Framework.Servers.HttpServer
1850 m_httpListener2.Start(64); 1868 m_httpListener2.Start(64);
1851 1869
1852 // Long Poll Service Manager with 3 worker threads a 25 second timeout for no events 1870 // Long Poll Service Manager with 3 worker threads a 25 second timeout for no events
1853// m_PollServiceManager = new PollServiceRequestManager(this, 3, 25000);
1854 m_PollServiceManager = new PollServiceRequestManager(this, 4, 25000); 1871 m_PollServiceManager = new PollServiceRequestManager(this, 4, 25000);
1872 m_PollServiceManager.Start();
1855 HTTPDRunning = true; 1873 HTTPDRunning = true;
1856 1874
1857 //HttpListenerContext context; 1875 //HttpListenerContext context;
@@ -1870,6 +1888,21 @@ namespace OpenSim.Framework.Servers.HttpServer
1870 // useful without inbound HTTP. 1888 // useful without inbound HTTP.
1871 throw e; 1889 throw e;
1872 } 1890 }
1891
1892 m_requestsProcessedStat
1893 = new Stat(
1894 "HTTPRequestsServed",
1895 "Number of inbound HTTP requests processed",
1896 "",
1897 "requests",
1898 "httpserver",
1899 Port.ToString(),
1900 StatType.Pull,
1901 MeasuresOfInterest.AverageChangeOverTime,
1902 stat => stat.Value = RequestNumber,
1903 StatVerbosity.Debug);
1904
1905 StatsManager.RegisterStat(m_requestsProcessedStat);
1873 } 1906 }
1874 1907
1875 public void httpServerDisconnectMonitor(IHttpClientContext source, SocketError err) 1908 public void httpServerDisconnectMonitor(IHttpClientContext source, SocketError err)
@@ -1902,9 +1935,12 @@ namespace OpenSim.Framework.Servers.HttpServer
1902 public void Stop() 1935 public void Stop()
1903 { 1936 {
1904 HTTPDRunning = false; 1937 HTTPDRunning = false;
1938
1939 StatsManager.DeregisterStat(m_requestsProcessedStat);
1940
1905 try 1941 try
1906 { 1942 {
1907// m_PollServiceManager.Stop(); 1943 m_PollServiceManager.Stop();
1908 1944
1909 m_httpListener2.ExceptionThrown -= httpServerException; 1945 m_httpListener2.ExceptionThrown -= httpServerException;
1910 //m_httpListener2.DisconnectHandler = null; 1946 //m_httpListener2.DisconnectHandler = null;
@@ -1931,6 +1967,7 @@ namespace OpenSim.Framework.Servers.HttpServer
1931 1967
1932 public void RemoveHTTPHandler(string httpMethod, string path) 1968 public void RemoveHTTPHandler(string httpMethod, string path)
1933 { 1969 {
1970 if (path == null) return; // Caps module isn't loaded, tries to remove handler where path = null
1934 lock (m_HTTPHandlers) 1971 lock (m_HTTPHandlers)
1935 { 1972 {
1936 if (httpMethod != null && httpMethod.Length == 0) 1973 if (httpMethod != null && httpMethod.Length == 0)
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseOutputStreamHandler.cs b/OpenSim/Framework/Servers/HttpServer/BaseOutputStreamHandler.cs
new file mode 100644
index 0000000..72b3065
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/BaseOutputStreamHandler.cs
@@ -0,0 +1,60 @@
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.IO;
29
30namespace OpenSim.Framework.Servers.HttpServer
31{
32 /// <summary>
33 /// Base handler for writing to an output stream
34 /// </summary>
35 /// <remarks>
36 /// Inheriting classes should override ProcessRequest() rather than Handle()
37 /// </remarks>
38 public abstract class BaseOutputStreamHandler : BaseRequestHandler, IRequestHandler
39 {
40 protected BaseOutputStreamHandler(string httpMethod, string path) : this(httpMethod, path, null, null) {}
41
42 protected BaseOutputStreamHandler(string httpMethod, string path, string name, string description)
43 : base(httpMethod, path, name, description) {}
44
45 public virtual void Handle(
46 string path, Stream request, Stream response, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
47 {
48 RequestsReceived++;
49
50 ProcessRequest(path, request, response, httpRequest, httpResponse);
51
52 RequestsHandled++;
53 }
54
55 protected virtual void ProcessRequest(
56 string path, Stream request, Stream response, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
57 {
58 }
59 }
60} \ No newline at end of file
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseRequestHandler.cs b/OpenSim/Framework/Servers/HttpServer/BaseRequestHandler.cs
index ae7aaf2..bbac699 100644
--- a/OpenSim/Framework/Servers/HttpServer/BaseRequestHandler.cs
+++ b/OpenSim/Framework/Servers/HttpServer/BaseRequestHandler.cs
@@ -31,6 +31,10 @@ namespace OpenSim.Framework.Servers.HttpServer
31{ 31{
32 public abstract class BaseRequestHandler 32 public abstract class BaseRequestHandler
33 { 33 {
34 public int RequestsReceived { get; protected set; }
35
36 public int RequestsHandled { get; protected set; }
37
34 public virtual string ContentType 38 public virtual string ContentType
35 { 39 {
36 get { return "application/xml"; } 40 get { return "application/xml"; }
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseStreamHandler.cs b/OpenSim/Framework/Servers/HttpServer/BaseStreamHandler.cs
index 6342983..252cc2a 100644
--- a/OpenSim/Framework/Servers/HttpServer/BaseStreamHandler.cs
+++ b/OpenSim/Framework/Servers/HttpServer/BaseStreamHandler.cs
@@ -29,14 +29,35 @@ using System.IO;
29 29
30namespace OpenSim.Framework.Servers.HttpServer 30namespace OpenSim.Framework.Servers.HttpServer
31{ 31{
32 /// <summary>
33 /// Base streamed request handler.
34 /// </summary>
35 /// <remarks>
36 /// Inheriting classes should override ProcessRequest() rather than Handle()
37 /// </remarks>
32 public abstract class BaseStreamHandler : BaseRequestHandler, IStreamedRequestHandler 38 public abstract class BaseStreamHandler : BaseRequestHandler, IStreamedRequestHandler
33 { 39 {
34 public abstract byte[] Handle(string path, Stream request,
35 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse);
36
37 protected BaseStreamHandler(string httpMethod, string path) : this(httpMethod, path, null, null) {} 40 protected BaseStreamHandler(string httpMethod, string path) : this(httpMethod, path, null, null) {}
38 41
39 protected BaseStreamHandler(string httpMethod, string path, string name, string description) 42 protected BaseStreamHandler(string httpMethod, string path, string name, string description)
40 : base(httpMethod, path, name, description) {} 43 : base(httpMethod, path, name, description) {}
44
45 public virtual byte[] Handle(
46 string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
47 {
48 RequestsReceived++;
49
50 byte[] result = ProcessRequest(path, request, httpRequest, httpResponse);
51
52 RequestsHandled++;
53
54 return result;
55 }
56
57 protected virtual byte[] ProcessRequest(
58 string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
59 {
60 return null;
61 }
41 } 62 }
42} \ No newline at end of file 63} \ No newline at end of file
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseStreamHandlerBasicDOSProtector.cs b/OpenSim/Framework/Servers/HttpServer/BaseStreamHandlerBasicDOSProtector.cs
new file mode 100644
index 0000000..1b88545
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/BaseStreamHandlerBasicDOSProtector.cs
@@ -0,0 +1,107 @@
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 */
27using OpenSim.Framework;
28using System.IO;
29
30namespace OpenSim.Framework.Servers.HttpServer
31{
32 /// <summary>
33 /// BaseStreamHandlerBasicDOSProtector Base streamed request handler.
34 /// </summary>
35 /// <remarks>
36 /// Inheriting classes should override ProcessRequest() rather than Handle()
37 /// </remarks>
38 public abstract class BaseStreamHandlerBasicDOSProtector : BaseRequestHandler, IStreamedRequestHandler
39 {
40
41 private readonly BasicDosProtectorOptions _options;
42 private readonly BasicDOSProtector _dosProtector;
43
44 protected BaseStreamHandlerBasicDOSProtector(string httpMethod, string path, BasicDosProtectorOptions options) : this(httpMethod, path, null, null, options) {}
45
46 protected BaseStreamHandlerBasicDOSProtector(string httpMethod, string path, string name, string description, BasicDosProtectorOptions options)
47 : base(httpMethod, path, name, description)
48 {
49 _options = options;
50 _dosProtector = new BasicDOSProtector(_options);
51 }
52
53 public virtual byte[] Handle(
54 string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
55 {
56 byte[] result;
57 RequestsReceived++;
58 string clientstring = GetClientString(httpRequest);
59 string endpoint = GetRemoteAddr(httpRequest);
60 if (_dosProtector.Process(clientstring, endpoint))
61 result = ProcessRequest(path, request, httpRequest, httpResponse);
62 else
63 result = ThrottledRequest(path, request, httpRequest, httpResponse);
64 if (_options.MaxConcurrentSessions > 0)
65 _dosProtector.ProcessEnd(clientstring, endpoint);
66
67 RequestsHandled++;
68
69 return result;
70 }
71
72 protected virtual byte[] ProcessRequest(
73 string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
74 {
75 return null;
76 }
77
78 protected virtual byte[] ThrottledRequest(
79 string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
80 {
81 return new byte[0];
82 }
83
84
85 private string GetRemoteAddr(IOSHttpRequest httpRequest)
86 {
87 string remoteaddr = string.Empty;
88 if (httpRequest.Headers["remote_addr"] != null)
89 remoteaddr = httpRequest.Headers["remote_addr"];
90
91 return remoteaddr;
92 }
93
94 private string GetClientString(IOSHttpRequest httpRequest)
95 {
96 string clientstring = string.Empty;
97
98 if (_options.AllowXForwardedFor && httpRequest.Headers["x-forwarded-for"] != null)
99 clientstring = httpRequest.Headers["x-forwarded-for"];
100 else
101 clientstring = GetRemoteAddr(httpRequest);
102
103 return clientstring;
104
105 }
106 }
107}
diff --git a/OpenSim/Framework/Servers/HttpServer/BinaryStreamHandler.cs b/OpenSim/Framework/Servers/HttpServer/BinaryStreamHandler.cs
index b94bfb4..1b03f54 100644
--- a/OpenSim/Framework/Servers/HttpServer/BinaryStreamHandler.cs
+++ b/OpenSim/Framework/Servers/HttpServer/BinaryStreamHandler.cs
@@ -45,7 +45,7 @@ namespace OpenSim.Framework.Servers.HttpServer
45 m_method = binaryMethod; 45 m_method = binaryMethod;
46 } 46 }
47 47
48 public override byte[] Handle(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 48 protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
49 { 49 {
50 byte[] data = ReadFully(request); 50 byte[] data = ReadFully(request);
51 string param = GetParam(path); 51 string param = GetParam(path);
diff --git a/OpenSim/Framework/Servers/HttpServer/GenericHTTPBasicDOSProtector.cs b/OpenSim/Framework/Servers/HttpServer/GenericHTTPBasicDOSProtector.cs
new file mode 100644
index 0000000..cd4b8ff
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/GenericHTTPBasicDOSProtector.cs
@@ -0,0 +1,119 @@
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.Collections;
29
30namespace OpenSim.Framework.Servers.HttpServer
31{
32 public class GenericHTTPDOSProtector
33 {
34 private readonly GenericHTTPMethod _normalMethod;
35 private readonly GenericHTTPMethod _throttledMethod;
36
37 private readonly BasicDosProtectorOptions _options;
38 private readonly BasicDOSProtector _dosProtector;
39
40 public GenericHTTPDOSProtector(GenericHTTPMethod normalMethod, GenericHTTPMethod throttledMethod, BasicDosProtectorOptions options)
41 {
42 _normalMethod = normalMethod;
43 _throttledMethod = throttledMethod;
44
45 _options = options;
46 _dosProtector = new BasicDOSProtector(_options);
47 }
48 public Hashtable Process(Hashtable request)
49 {
50 Hashtable process = null;
51 string clientstring= GetClientString(request);
52 string endpoint = GetRemoteAddr(request);
53 if (_dosProtector.Process(clientstring, endpoint))
54 process = _normalMethod(request);
55 else
56 process = _throttledMethod(request);
57
58 if (_options.MaxConcurrentSessions>0)
59 _dosProtector.ProcessEnd(clientstring, endpoint);
60
61 return process;
62 }
63
64 private string GetRemoteAddr(Hashtable request)
65 {
66 string remoteaddr = "";
67 if (!request.ContainsKey("headers"))
68 return remoteaddr;
69 Hashtable requestinfo = (Hashtable)request["headers"];
70 if (!requestinfo.ContainsKey("remote_addr"))
71 return remoteaddr;
72 object remote_addrobj = requestinfo["remote_addr"];
73 if (remote_addrobj != null)
74 {
75 if (!string.IsNullOrEmpty(remote_addrobj.ToString()))
76 {
77 remoteaddr = remote_addrobj.ToString();
78 }
79
80 }
81 return remoteaddr;
82 }
83
84 private string GetClientString(Hashtable request)
85 {
86 string clientstring = "";
87 if (!request.ContainsKey("headers"))
88 return clientstring;
89
90 Hashtable requestinfo = (Hashtable)request["headers"];
91 if (_options.AllowXForwardedFor && requestinfo.ContainsKey("x-forwarded-for"))
92 {
93 object str = requestinfo["x-forwarded-for"];
94 if (str != null)
95 {
96 if (!string.IsNullOrEmpty(str.ToString()))
97 {
98 return str.ToString();
99 }
100 }
101 }
102 if (!requestinfo.ContainsKey("remote_addr"))
103 return clientstring;
104
105 object remote_addrobj = requestinfo["remote_addr"];
106 if (remote_addrobj != null)
107 {
108 if (!string.IsNullOrEmpty(remote_addrobj.ToString()))
109 {
110 clientstring = remote_addrobj.ToString();
111 }
112 }
113
114 return clientstring;
115
116 }
117
118 }
119}
diff --git a/OpenSim/Framework/Servers/HttpServer/Interfaces/IStreamHandler.cs b/OpenSim/Framework/Servers/HttpServer/Interfaces/IStreamHandler.cs
index cb5cce5..b8541cb 100644
--- a/OpenSim/Framework/Servers/HttpServer/Interfaces/IStreamHandler.cs
+++ b/OpenSim/Framework/Servers/HttpServer/Interfaces/IStreamHandler.cs
@@ -32,7 +32,6 @@ namespace OpenSim.Framework.Servers.HttpServer
32{ 32{
33 public interface IRequestHandler 33 public interface IRequestHandler
34 { 34 {
35
36 /// <summary> 35 /// <summary>
37 /// Name for this handler. 36 /// Name for this handler.
38 /// </summary> 37 /// </summary>
@@ -59,6 +58,19 @@ namespace OpenSim.Framework.Servers.HttpServer
59 58
60 // Return path 59 // Return path
61 string Path { get; } 60 string Path { get; }
61
62 /// <summary>
63 /// Number of requests received by this handler
64 /// </summary>
65 int RequestsReceived { get; }
66
67 /// <summary>
68 /// Number of requests handled.
69 /// </summary>
70 /// <remarks>
71 /// Should be equal to RequestsReceived unless requested are being handled slowly or there is deadlock.
72 /// </remarks>
73 int RequestsHandled { get; }
62 } 74 }
63 75
64 public interface IStreamedRequestHandler : IRequestHandler 76 public interface IStreamedRequestHandler : IRequestHandler
@@ -69,7 +81,6 @@ namespace OpenSim.Framework.Servers.HttpServer
69 81
70 public interface IStreamHandler : IRequestHandler 82 public interface IStreamHandler : IRequestHandler
71 { 83 {
72 // Handle request stream, return byte array
73 void Handle(string path, Stream request, Stream response, IOSHttpRequest httpReqbuest, IOSHttpResponse httpResponse); 84 void Handle(string path, Stream request, Stream response, IOSHttpRequest httpReqbuest, IOSHttpResponse httpResponse);
74 } 85 }
75 86
diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs
index c19ac32..3fd3bf7 100644
--- a/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs
+++ b/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs
@@ -50,25 +50,39 @@ namespace OpenSim.Framework.Servers.HttpServer
50 50
51 public enum EventType : int 51 public enum EventType : int
52 { 52 {
53 Normal = 0, 53 LongPoll = 0,
54 LslHttp = 1, 54 LslHttp = 1,
55 Inventory = 2, 55 Inventory = 2,
56 Texture = 3, 56 Texture = 3,
57 Mesh = 4 57 Mesh = 4
58 } 58 }
59 59
60 public string Url { get; set; }
61
62 /// <summary>
63 /// Number of requests received for this poll service.
64 /// </summary>
65 public int RequestsReceived { get; set; }
66
67 /// <summary>
68 /// Number of requests handled by this poll service.
69 /// </summary>
70 public int RequestsHandled { get; set; }
71
60 public PollServiceEventArgs( 72 public PollServiceEventArgs(
61 RequestMethod pRequest, 73 RequestMethod pRequest,
74 string pUrl,
62 HasEventsMethod pHasEvents, GetEventsMethod pGetEvents, NoEventsMethod pNoEvents, 75 HasEventsMethod pHasEvents, GetEventsMethod pGetEvents, NoEventsMethod pNoEvents,
63 UUID pId, int pTimeOutms) 76 UUID pId, int pTimeOutms)
64 { 77 {
65 Request = pRequest; 78 Request = pRequest;
79 Url = pUrl;
66 HasEvents = pHasEvents; 80 HasEvents = pHasEvents;
67 GetEvents = pGetEvents; 81 GetEvents = pGetEvents;
68 NoEvents = pNoEvents; 82 NoEvents = pNoEvents;
69 Id = pId; 83 Id = pId;
70 TimeOutms = pTimeOutms; 84 TimeOutms = pTimeOutms;
71 Type = EventType.Normal; 85 Type = EventType.LongPoll;
72 } 86 }
73 } 87 }
74} 88}
diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs
index 723530a..6aa9479 100644
--- a/OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs
+++ b/OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs
@@ -26,13 +26,19 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections;
30using System.Reflection;
31using System.Text;
29using HttpServer; 32using HttpServer;
33using log4net;
30using OpenMetaverse; 34using OpenMetaverse;
31 35
32namespace OpenSim.Framework.Servers.HttpServer 36namespace OpenSim.Framework.Servers.HttpServer
33{ 37{
34 public class PollServiceHttpRequest 38 public class PollServiceHttpRequest
35 { 39 {
40 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
41
36 public readonly PollServiceEventArgs PollServiceArgs; 42 public readonly PollServiceEventArgs PollServiceArgs;
37 public readonly IHttpClientContext HttpContext; 43 public readonly IHttpClientContext HttpContext;
38 public readonly IHttpRequest Request; 44 public readonly IHttpRequest Request;
@@ -48,5 +54,44 @@ namespace OpenSim.Framework.Servers.HttpServer
48 RequestTime = System.Environment.TickCount; 54 RequestTime = System.Environment.TickCount;
49 RequestID = UUID.Random(); 55 RequestID = UUID.Random();
50 } 56 }
57
58 internal void DoHTTPGruntWork(BaseHttpServer server, Hashtable responsedata)
59 {
60 OSHttpResponse response
61 = new OSHttpResponse(new HttpResponse(HttpContext, Request), HttpContext);
62
63 byte[] buffer = server.DoHTTPGruntWork(responsedata, response);
64
65 response.SendChunked = false;
66 response.ContentLength64 = buffer.Length;
67 response.ContentEncoding = Encoding.UTF8;
68
69 try
70 {
71 response.OutputStream.Write(buffer, 0, buffer.Length);
72 }
73 catch (Exception ex)
74 {
75 m_log.Warn(string.Format("[POLL SERVICE WORKER THREAD]: Error ", ex));
76 }
77 finally
78 {
79 //response.OutputStream.Close();
80 try
81 {
82 response.OutputStream.Flush();
83 response.Send();
84
85 //if (!response.KeepAlive && response.ReuseContext)
86 // response.FreeContext();
87 }
88 catch (Exception e)
89 {
90 m_log.Warn(String.Format("[POLL SERVICE WORKER THREAD]: Error ", e));
91 }
92
93 PollServiceArgs.RequestsHandled++;
94 }
95 }
51 } 96 }
52} \ No newline at end of file 97} \ No newline at end of file
diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
index 5406f00..44f7045 100644
--- a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
+++ b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
@@ -64,14 +64,17 @@ namespace OpenSim.Framework.Servers.HttpServer
64 m_server = pSrv; 64 m_server = pSrv;
65 m_WorkerThreadCount = pWorkerThreadCount; 65 m_WorkerThreadCount = pWorkerThreadCount;
66 m_workerThreads = new Thread[m_WorkerThreadCount]; 66 m_workerThreads = new Thread[m_WorkerThreadCount];
67 }
67 68
69 public void Start()
70 {
68 //startup worker threads 71 //startup worker threads
69 for (uint i = 0; i < m_WorkerThreadCount; i++) 72 for (uint i = 0; i < m_WorkerThreadCount; i++)
70 { 73 {
71 m_workerThreads[i] 74 m_workerThreads[i]
72 = Watchdog.StartThread( 75 = Watchdog.StartThread(
73 PoolWorkerJob, 76 PoolWorkerJob,
74 String.Format("PollServiceWorkerThread{0}", i), 77 string.Format("PollServiceWorkerThread{0}:{1}", i, m_server.Port),
75 ThreadPriority.Normal, 78 ThreadPriority.Normal,
76 false, 79 false,
77 false, 80 false,
@@ -81,7 +84,7 @@ namespace OpenSim.Framework.Servers.HttpServer
81 84
82 m_retrysThread = Watchdog.StartThread( 85 m_retrysThread = Watchdog.StartThread(
83 this.CheckRetries, 86 this.CheckRetries,
84 "PollServiceWatcherThread", 87 string.Format("PollServiceWatcherThread:{0}", m_server.Port),
85 ThreadPriority.Normal, 88 ThreadPriority.Normal,
86 false, 89 false,
87 true, 90 true,
@@ -89,7 +92,6 @@ namespace OpenSim.Framework.Servers.HttpServer
89 1000 * 60 * 10); 92 1000 * 60 * 10);
90 } 93 }
91 94
92
93 private void ReQueueEvent(PollServiceHttpRequest req) 95 private void ReQueueEvent(PollServiceHttpRequest req)
94 { 96 {
95 if (m_running) 97 if (m_running)
@@ -103,7 +105,7 @@ namespace OpenSim.Framework.Servers.HttpServer
103 { 105 {
104 if (m_running) 106 if (m_running)
105 { 107 {
106 if (req.PollServiceArgs.Type != PollServiceEventArgs.EventType.Normal) 108 if (req.PollServiceArgs.Type != PollServiceEventArgs.EventType.LongPoll)
107 { 109 {
108 m_requests.Enqueue(req); 110 m_requests.Enqueue(req);
109 } 111 }
@@ -140,13 +142,13 @@ namespace OpenSim.Framework.Servers.HttpServer
140 } 142 }
141 } 143 }
142 144
143 ~PollServiceRequestManager() 145 public void Stop()
144 { 146 {
145 m_running = false; 147 m_running = false;
146 Thread.Sleep(1000); // let the world move 148 Thread.Sleep(1000); // let the world move
147 149
148 foreach (Thread t in m_workerThreads) 150 foreach (Thread t in m_workerThreads)
149 Watchdog.AbortThread(t.ManagedThreadId); 151 Watchdog.AbortThread(t.ManagedThreadId);
150 152
151 try 153 try
152 { 154 {
@@ -205,7 +207,7 @@ namespace OpenSim.Framework.Servers.HttpServer
205 if (responsedata == null) 207 if (responsedata == null)
206 continue; 208 continue;
207 209
208 if (req.PollServiceArgs.Type == PollServiceEventArgs.EventType.Normal) // This is the event queue 210 if (req.PollServiceArgs.Type == PollServiceEventArgs.EventType.LongPoll) // This is the event queue
209 { 211 {
210 try 212 try
211 { 213 {
diff --git a/OpenSim/Framework/Servers/HttpServer/Properties/AssemblyInfo.cs b/OpenSim/Framework/Servers/HttpServer/Properties/AssemblyInfo.cs
index 8e592c1..f409667 100644
--- a/OpenSim/Framework/Servers/HttpServer/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/Servers/HttpServer/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Framework/Servers/HttpServer/RestDeserialiseHandler.cs b/OpenSim/Framework/Servers/HttpServer/RestDeserialiseHandler.cs
index 07082a8..bd55657 100644
--- a/OpenSim/Framework/Servers/HttpServer/RestDeserialiseHandler.cs
+++ b/OpenSim/Framework/Servers/HttpServer/RestDeserialiseHandler.cs
@@ -33,7 +33,7 @@ namespace OpenSim.Framework.Servers.HttpServer
33{ 33{
34 public delegate TResponse RestDeserialiseMethod<TRequest, TResponse>(TRequest request); 34 public delegate TResponse RestDeserialiseMethod<TRequest, TResponse>(TRequest request);
35 35
36 public class RestDeserialiseHandler<TRequest, TResponse> : BaseRequestHandler, IStreamHandler 36 public class RestDeserialiseHandler<TRequest, TResponse> : BaseOutputStreamHandler, IStreamHandler
37 where TRequest : new() 37 where TRequest : new()
38 { 38 {
39 private RestDeserialiseMethod<TRequest, TResponse> m_method; 39 private RestDeserialiseMethod<TRequest, TResponse> m_method;
@@ -48,7 +48,7 @@ namespace OpenSim.Framework.Servers.HttpServer
48 m_method = method; 48 m_method = method;
49 } 49 }
50 50
51 public void Handle(string path, Stream request, Stream responseStream, 51 protected override void ProcessRequest(string path, Stream request, Stream responseStream,
52 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 52 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
53 { 53 {
54 TRequest deserial; 54 TRequest deserial;
diff --git a/OpenSim/Framework/Servers/HttpServer/RestSessionService.cs b/OpenSim/Framework/Servers/HttpServer/RestSessionService.cs
index edcd134..83c9848 100644
--- a/OpenSim/Framework/Servers/HttpServer/RestSessionService.cs
+++ b/OpenSim/Framework/Servers/HttpServer/RestSessionService.cs
@@ -183,7 +183,7 @@ namespace OpenSim.Framework.Servers.HttpServer
183 183
184 public delegate bool CheckIdentityMethod(string sid, string aid); 184 public delegate bool CheckIdentityMethod(string sid, string aid);
185 185
186 public class RestDeserialiseSecureHandler<TRequest, TResponse> : BaseRequestHandler, IStreamHandler 186 public class RestDeserialiseSecureHandler<TRequest, TResponse> : BaseOutputStreamHandler, IStreamHandler
187 where TRequest : new() 187 where TRequest : new()
188 { 188 {
189 private static readonly ILog m_log 189 private static readonly ILog m_log
@@ -201,7 +201,7 @@ namespace OpenSim.Framework.Servers.HttpServer
201 m_method = method; 201 m_method = method;
202 } 202 }
203 203
204 public void Handle(string path, Stream request, Stream responseStream, 204 protected override void ProcessRequest(string path, Stream request, Stream responseStream,
205 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 205 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
206 { 206 {
207 RestSessionObject<TRequest> deserial = default(RestSessionObject<TRequest>); 207 RestSessionObject<TRequest> deserial = default(RestSessionObject<TRequest>);
@@ -237,7 +237,7 @@ namespace OpenSim.Framework.Servers.HttpServer
237 237
238 public delegate bool CheckTrustedSourceMethod(IPEndPoint peer); 238 public delegate bool CheckTrustedSourceMethod(IPEndPoint peer);
239 239
240 public class RestDeserialiseTrustedHandler<TRequest, TResponse> : BaseRequestHandler, IStreamHandler 240 public class RestDeserialiseTrustedHandler<TRequest, TResponse> : BaseOutputStreamHandler, IStreamHandler
241 where TRequest : new() 241 where TRequest : new()
242 { 242 {
243 private static readonly ILog m_log 243 private static readonly ILog m_log
@@ -260,7 +260,7 @@ namespace OpenSim.Framework.Servers.HttpServer
260 m_method = method; 260 m_method = method;
261 } 261 }
262 262
263 public void Handle(string path, Stream request, Stream responseStream, 263 protected override void ProcessRequest(string path, Stream request, Stream responseStream,
264 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 264 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
265 { 265 {
266 TRequest deserial = default(TRequest); 266 TRequest deserial = default(TRequest);
@@ -292,6 +292,5 @@ namespace OpenSim.Framework.Servers.HttpServer
292 serializer.Serialize(xmlWriter, response); 292 serializer.Serialize(xmlWriter, response);
293 } 293 }
294 } 294 }
295 } 295 }
296 296} \ No newline at end of file
297}
diff --git a/OpenSim/Framework/Servers/HttpServer/RestStreamHandler.cs b/OpenSim/Framework/Servers/HttpServer/RestStreamHandler.cs
index 1f17fee..0305dee 100644
--- a/OpenSim/Framework/Servers/HttpServer/RestStreamHandler.cs
+++ b/OpenSim/Framework/Servers/HttpServer/RestStreamHandler.cs
@@ -48,7 +48,7 @@ namespace OpenSim.Framework.Servers.HttpServer
48 m_restMethod = restMethod; 48 m_restMethod = restMethod;
49 } 49 }
50 50
51 public override byte[] Handle(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 51 protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
52 { 52 {
53 Encoding encoding = Encoding.UTF8; 53 Encoding encoding = Encoding.UTF8;
54 StreamReader streamReader = new StreamReader(request, encoding); 54 StreamReader streamReader = new StreamReader(request, encoding);
diff --git a/OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs b/OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs
index ee96b47..c2925e3 100644
--- a/OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs
+++ b/OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs
@@ -28,8 +28,10 @@
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.IO; 30using System.IO;
31using System.Net;
31using System.Security.Cryptography; 32using System.Security.Cryptography;
32using System.Text; 33using System.Text;
34using System.Threading;
33using HttpServer; 35using HttpServer;
34 36
35namespace OpenSim.Framework.Servers.HttpServer 37namespace OpenSim.Framework.Servers.HttpServer
@@ -75,7 +77,7 @@ namespace OpenSim.Framework.Servers.HttpServer
75 /// <summary> 77 /// <summary>
76 /// This is a regular HTTP Request... This may be removed in the future. 78 /// This is a regular HTTP Request... This may be removed in the future.
77 /// </summary> 79 /// </summary>
78 public event RegularHttpRequestDelegate OnRegularHttpRequest; 80// public event RegularHttpRequestDelegate OnRegularHttpRequest;
79 81
80 /// <summary> 82 /// <summary>
81 /// When the upgrade from a HTTP request to a Websocket is completed, this will be fired 83 /// When the upgrade from a HTTP request to a Websocket is completed, this will be fired
@@ -98,6 +100,8 @@ namespace OpenSim.Framework.Servers.HttpServer
98 /// </summary> 100 /// </summary>
99 public ValidateHandshake HandshakeValidateMethodOverride = null; 101 public ValidateHandshake HandshakeValidateMethodOverride = null;
100 102
103 private ManualResetEvent _receiveDone = new ManualResetEvent(false);
104
101 private OSHttpRequest _request; 105 private OSHttpRequest _request;
102 private HTTPNetworkContext _networkContext; 106 private HTTPNetworkContext _networkContext;
103 private IHttpClientContext _clientContext; 107 private IHttpClientContext _clientContext;
@@ -109,6 +113,8 @@ namespace OpenSim.Framework.Servers.HttpServer
109 private bool _closing; 113 private bool _closing;
110 private bool _upgraded; 114 private bool _upgraded;
111 private int _maxPayloadBytes = 41943040; 115 private int _maxPayloadBytes = 41943040;
116 private int _initialMsgTimeout = 0;
117 private int _defaultReadTimeout = 10000;
112 118
113 private const string HandshakeAcceptText = 119 private const string HandshakeAcceptText =
114 "HTTP/1.1 101 Switching Protocols\r\n" + 120 "HTTP/1.1 101 Switching Protocols\r\n" +
@@ -131,6 +137,7 @@ namespace OpenSim.Framework.Servers.HttpServer
131 { 137 {
132 _request = preq; 138 _request = preq;
133 _networkContext = pContext.GiveMeTheNetworkStreamIKnowWhatImDoing(); 139 _networkContext = pContext.GiveMeTheNetworkStreamIKnowWhatImDoing();
140 _networkContext.Stream.ReadTimeout = _defaultReadTimeout;
134 _clientContext = pContext; 141 _clientContext = pContext;
135 _bufferLength = bufferlen; 142 _bufferLength = bufferlen;
136 _buffer = new byte[_bufferLength]; 143 _buffer = new byte[_bufferLength];
@@ -206,6 +213,16 @@ namespace OpenSim.Framework.Servers.HttpServer
206 } 213 }
207 214
208 /// <summary> 215 /// <summary>
216 /// Set this to the maximum amount of milliseconds to wait for the first complete message to be sent or received on the websocket after upgrading
217 /// Default, it waits forever. Use this when your Websocket consuming code opens a connection and waits for a message from the other side to avoid a Denial of Service vector.
218 /// </summary>
219 public int InitialMsgTimeout
220 {
221 get { return _initialMsgTimeout; }
222 set { _initialMsgTimeout = value; }
223 }
224
225 /// <summary>
209 /// This triggers the websocket start the upgrade process 226 /// This triggers the websocket start the upgrade process
210 /// </summary> 227 /// </summary>
211 public void HandshakeAndUpgrade() 228 public void HandshakeAndUpgrade()
@@ -245,6 +262,7 @@ namespace OpenSim.Framework.Servers.HttpServer
245 string rawaccept = string.Format(HandshakeAcceptText, acceptKey); 262 string rawaccept = string.Format(HandshakeAcceptText, acceptKey);
246 SendUpgradeSuccess(rawaccept); 263 SendUpgradeSuccess(rawaccept);
247 264
265
248 } 266 }
249 else 267 else
250 { 268 {
@@ -258,6 +276,10 @@ namespace OpenSim.Framework.Servers.HttpServer
258 SendUpgradeSuccess(rawaccept); 276 SendUpgradeSuccess(rawaccept);
259 } 277 }
260 } 278 }
279 public IPEndPoint GetRemoteIPEndpoint()
280 {
281 return _request.RemoteIPEndPoint;
282 }
261 283
262 /// <summary> 284 /// <summary>
263 /// Generates a handshake response key string based on the client's 285 /// Generates a handshake response key string based on the client's
@@ -290,9 +312,16 @@ namespace OpenSim.Framework.Servers.HttpServer
290 WebSocketState socketState = new WebSocketState() { ReceivedBytes = new List<byte>(), Header = WebsocketFrameHeader.HeaderDefault(), FrameComplete = true}; 312 WebSocketState socketState = new WebSocketState() { ReceivedBytes = new List<byte>(), Header = WebsocketFrameHeader.HeaderDefault(), FrameComplete = true};
291 313
292 byte[] bhandshakeResponse = Encoding.UTF8.GetBytes(pHandshakeResponse); 314 byte[] bhandshakeResponse = Encoding.UTF8.GetBytes(pHandshakeResponse);
315
316
317
318
293 try 319 try
294 { 320 {
295 321 if (_initialMsgTimeout > 0)
322 {
323 _receiveDone.Reset();
324 }
296 // Begin reading the TCP stream before writing the Upgrade success message to the other side of the stream. 325 // Begin reading the TCP stream before writing the Upgrade success message to the other side of the stream.
297 _networkContext.Stream.BeginRead(_buffer, 0, _bufferLength, OnReceive, socketState); 326 _networkContext.Stream.BeginRead(_buffer, 0, _bufferLength, OnReceive, socketState);
298 327
@@ -303,16 +332,20 @@ namespace OpenSim.Framework.Servers.HttpServer
303 UpgradeCompletedDelegate d = OnUpgradeCompleted; 332 UpgradeCompletedDelegate d = OnUpgradeCompleted;
304 if (d != null) 333 if (d != null)
305 d(this, new UpgradeCompletedEventArgs()); 334 d(this, new UpgradeCompletedEventArgs());
335 if (_initialMsgTimeout > 0)
336 {
337 if (!_receiveDone.WaitOne(TimeSpan.FromMilliseconds(_initialMsgTimeout)))
338 Close(string.Empty);
339 }
306 } 340 }
307 catch (IOException fail) 341 catch (IOException)
308 { 342 {
309 Close(string.Empty); 343 Close(string.Empty);
310 } 344 }
311 catch (ObjectDisposedException fail) 345 catch (ObjectDisposedException)
312 { 346 {
313 Close(string.Empty); 347 Close(string.Empty);
314 } 348 }
315
316 } 349 }
317 350
318 /// <summary> 351 /// <summary>
@@ -414,8 +447,6 @@ namespace OpenSim.Framework.Servers.HttpServer
414 _socketState.Header = pheader; 447 _socketState.Header = pheader;
415 } 448 }
416 449
417
418
419 if (_socketState.FrameComplete) 450 if (_socketState.FrameComplete)
420 { 451 {
421 ProcessFrame(_socketState); 452 ProcessFrame(_socketState);
@@ -424,7 +455,6 @@ namespace OpenSim.Framework.Servers.HttpServer
424 _socketState.ExpectedBytes = 0; 455 _socketState.ExpectedBytes = 0;
425 456
426 } 457 }
427
428 } 458 }
429 } 459 }
430 else 460 else
@@ -457,8 +487,7 @@ namespace OpenSim.Framework.Servers.HttpServer
457 _socketState.ReceivedBytes.Clear(); 487 _socketState.ReceivedBytes.Clear();
458 _socketState.ExpectedBytes = 0; 488 _socketState.ExpectedBytes = 0;
459 // do some processing 489 // do some processing
460 } 490 }
461
462 } 491 }
463 } 492 }
464 if (offset > 0) 493 if (offset > 0)
@@ -477,13 +506,12 @@ namespace OpenSim.Framework.Servers.HttpServer
477 { 506 {
478 // We can't read the stream anymore... 507 // We can't read the stream anymore...
479 } 508 }
480
481 } 509 }
482 catch (IOException fail) 510 catch (IOException)
483 { 511 {
484 Close(string.Empty); 512 Close(string.Empty);
485 } 513 }
486 catch (ObjectDisposedException fail) 514 catch (ObjectDisposedException)
487 { 515 {
488 Close(string.Empty); 516 Close(string.Empty);
489 } 517 }
@@ -495,6 +523,11 @@ namespace OpenSim.Framework.Servers.HttpServer
495 /// <param name="message">the string message that is to be sent</param> 523 /// <param name="message">the string message that is to be sent</param>
496 public void SendMessage(string message) 524 public void SendMessage(string message)
497 { 525 {
526 if (_initialMsgTimeout > 0)
527 {
528 _receiveDone.Set();
529 _initialMsgTimeout = 0;
530 }
498 byte[] messagedata = Encoding.UTF8.GetBytes(message); 531 byte[] messagedata = Encoding.UTF8.GetBytes(message);
499 WebSocketFrame textMessageFrame = new WebSocketFrame() { Header = WebsocketFrameHeader.HeaderDefault(), WebSocketPayload = messagedata }; 532 WebSocketFrame textMessageFrame = new WebSocketFrame() { Header = WebsocketFrameHeader.HeaderDefault(), WebSocketPayload = messagedata };
500 textMessageFrame.Header.Opcode = WebSocketReader.OpCode.Text; 533 textMessageFrame.Header.Opcode = WebSocketReader.OpCode.Text;
@@ -505,6 +538,11 @@ namespace OpenSim.Framework.Servers.HttpServer
505 538
506 public void SendData(byte[] data) 539 public void SendData(byte[] data)
507 { 540 {
541 if (_initialMsgTimeout > 0)
542 {
543 _receiveDone.Set();
544 _initialMsgTimeout = 0;
545 }
508 WebSocketFrame dataMessageFrame = new WebSocketFrame() { Header = WebsocketFrameHeader.HeaderDefault(), WebSocketPayload = data}; 546 WebSocketFrame dataMessageFrame = new WebSocketFrame() { Header = WebsocketFrameHeader.HeaderDefault(), WebSocketPayload = data};
509 dataMessageFrame.Header.IsEnd = true; 547 dataMessageFrame.Header.IsEnd = true;
510 dataMessageFrame.Header.Opcode = WebSocketReader.OpCode.Binary; 548 dataMessageFrame.Header.Opcode = WebSocketReader.OpCode.Binary;
@@ -537,6 +575,11 @@ namespace OpenSim.Framework.Servers.HttpServer
537 /// </summary> 575 /// </summary>
538 public void SendPingCheck() 576 public void SendPingCheck()
539 { 577 {
578 if (_initialMsgTimeout > 0)
579 {
580 _receiveDone.Set();
581 _initialMsgTimeout = 0;
582 }
540 WebSocketFrame pingFrame = new WebSocketFrame() { Header = WebsocketFrameHeader.HeaderDefault(), WebSocketPayload = new byte[0] }; 583 WebSocketFrame pingFrame = new WebSocketFrame() { Header = WebsocketFrameHeader.HeaderDefault(), WebSocketPayload = new byte[0] };
541 pingFrame.Header.Opcode = WebSocketReader.OpCode.Ping; 584 pingFrame.Header.Opcode = WebSocketReader.OpCode.Ping;
542 pingFrame.Header.IsEnd = true; 585 pingFrame.Header.IsEnd = true;
@@ -550,6 +593,11 @@ namespace OpenSim.Framework.Servers.HttpServer
550 /// <param name="message"></param> 593 /// <param name="message"></param>
551 public void Close(string message) 594 public void Close(string message)
552 { 595 {
596 if (_initialMsgTimeout > 0)
597 {
598 _receiveDone.Set();
599 _initialMsgTimeout = 0;
600 }
553 if (_networkContext == null) 601 if (_networkContext == null)
554 return; 602 return;
555 if (_networkContext.Stream != null) 603 if (_networkContext.Stream != null)
@@ -589,7 +637,11 @@ namespace OpenSim.Framework.Servers.HttpServer
589 WebSocketReader.Mask(psocketState.Header.Mask, unmask); 637 WebSocketReader.Mask(psocketState.Header.Mask, unmask);
590 psocketState.ReceivedBytes = new List<byte>(unmask); 638 psocketState.ReceivedBytes = new List<byte>(unmask);
591 } 639 }
592 640 if (psocketState.Header.Opcode != WebSocketReader.OpCode.Continue && _initialMsgTimeout > 0)
641 {
642 _receiveDone.Set();
643 _initialMsgTimeout = 0;
644 }
593 switch (psocketState.Header.Opcode) 645 switch (psocketState.Header.Opcode)
594 { 646 {
595 case WebSocketReader.OpCode.Ping: 647 case WebSocketReader.OpCode.Ping:
@@ -702,6 +754,11 @@ namespace OpenSim.Framework.Servers.HttpServer
702 } 754 }
703 public void Dispose() 755 public void Dispose()
704 { 756 {
757 if (_initialMsgTimeout > 0)
758 {
759 _receiveDone.Set();
760 _initialMsgTimeout = 0;
761 }
705 if (_networkContext != null && _networkContext.Stream != null) 762 if (_networkContext != null && _networkContext.Stream != null)
706 { 763 {
707 if (_networkContext.Stream.CanWrite) 764 if (_networkContext.Stream.CanWrite)
diff --git a/OpenSim/Framework/Servers/HttpServer/XmlRpcBasicDOSProtector.cs b/OpenSim/Framework/Servers/HttpServer/XmlRpcBasicDOSProtector.cs
new file mode 100644
index 0000000..f212208
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/XmlRpcBasicDOSProtector.cs
@@ -0,0 +1,91 @@
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.Net;
29using Nwc.XmlRpc;
30using OpenSim.Framework;
31
32
33namespace OpenSim.Framework.Servers.HttpServer
34{
35 public class XmlRpcBasicDOSProtector
36 {
37 private readonly XmlRpcMethod _normalMethod;
38 private readonly XmlRpcMethod _throttledMethod;
39
40 private readonly BasicDosProtectorOptions _options;
41 private readonly BasicDOSProtector _dosProtector;
42
43 public XmlRpcBasicDOSProtector(XmlRpcMethod normalMethod, XmlRpcMethod throttledMethod,BasicDosProtectorOptions options)
44 {
45 _normalMethod = normalMethod;
46 _throttledMethod = throttledMethod;
47
48 _options = options;
49 _dosProtector = new BasicDOSProtector(_options);
50
51 }
52 public XmlRpcResponse Process(XmlRpcRequest request, IPEndPoint client)
53 {
54
55 XmlRpcResponse resp = null;
56 string clientstring = GetClientString(request, client);
57 string endpoint = GetEndPoint(request, client);
58 if (_dosProtector.Process(clientstring, endpoint))
59 resp = _normalMethod(request, client);
60 else
61 resp = _throttledMethod(request, client);
62 if (_options.MaxConcurrentSessions > 0)
63 _dosProtector.ProcessEnd(clientstring, endpoint);
64 return resp;
65 }
66
67 private string GetClientString(XmlRpcRequest request, IPEndPoint client)
68 {
69 string clientstring;
70 if (_options.AllowXForwardedFor && request.Params.Count > 3)
71 {
72 object headerstr = request.Params[3];
73 if (headerstr != null && !string.IsNullOrEmpty(headerstr.ToString()))
74 clientstring = request.Params[3].ToString();
75 else
76 clientstring = client.Address.ToString();
77 }
78 else
79 clientstring = client.Address.ToString();
80 return clientstring;
81 }
82
83 private string GetEndPoint(XmlRpcRequest request, IPEndPoint client)
84 {
85 return client.Address.ToString();
86 }
87
88 }
89
90
91}
diff --git a/OpenSim/Framework/Servers/MainServer.cs b/OpenSim/Framework/Servers/MainServer.cs
index cfd34bb..57931d4 100644
--- a/OpenSim/Framework/Servers/MainServer.cs
+++ b/OpenSim/Framework/Servers/MainServer.cs
@@ -121,12 +121,14 @@ namespace OpenSim.Framework.Servers
121 + " level >= 2 then long warnings are logged when receiving bad input data.\n" 121 + " level >= 2 then long warnings are logged when receiving bad input data.\n"
122 + " level >= 3 then short notices about all incoming non-poll HTTP requests are logged.\n" 122 + " level >= 3 then short notices about all incoming non-poll HTTP requests are logged.\n"
123 + " level >= 4 then the time taken to fulfill the request is logged.\n" 123 + " level >= 4 then the time taken to fulfill the request is logged.\n"
124 + " level >= 5 then a sample from the beginning of the incoming data is logged.\n" 124 + " level >= 5 then a sample from the beginning of the data is logged.\n"
125 + " level >= 6 then the entire incoming data is logged.\n" 125 + " level >= 6 then the entire data is logged.\n"
126 + " no level is specified then the current level is returned.\n\n" 126 + " no level is specified then the current level is returned.\n\n"
127 + "If out or all and\n" 127 + "If out or all and\n"
128 + " level >= 3 then short notices about all outgoing requests going through WebUtil are logged.\n" 128 + " level >= 3 then short notices about all outgoing requests going through WebUtil are logged.\n"
129 + " level >= 4 then the time taken to fulfill the request is logged.\n", 129 + " level >= 4 then the time taken to fulfill the request is logged.\n"
130 + " level >= 5 then a sample from the beginning of the data is logged.\n"
131 + " level >= 6 then the entire data is logged.\n",
130 HandleDebugHttpCommand); 132 HandleDebugHttpCommand);
131 } 133 }
132 134
@@ -283,7 +285,12 @@ namespace OpenSim.Framework.Servers
283 public static bool RemoveHttpServer(uint port) 285 public static bool RemoveHttpServer(uint port)
284 { 286 {
285 lock (m_Servers) 287 lock (m_Servers)
288 {
289 if (instance != null && instance.Port == port)
290 instance = null;
291
286 return m_Servers.Remove(port); 292 return m_Servers.Remove(port);
293 }
287 } 294 }
288 295
289 /// <summary> 296 /// <summary>
diff --git a/OpenSim/Framework/Servers/ServerBase.cs b/OpenSim/Framework/Servers/ServerBase.cs
index 1ff8aca..7108314 100644
--- a/OpenSim/Framework/Servers/ServerBase.cs
+++ b/OpenSim/Framework/Servers/ServerBase.cs
@@ -62,6 +62,8 @@ namespace OpenSim.Framework.Servers
62 62
63 protected string m_pidFile = String.Empty; 63 protected string m_pidFile = String.Empty;
64 64
65 protected ServerStatsCollector m_serverStatsCollector;
66
65 /// <summary> 67 /// <summary>
66 /// Server version information. Usually VersionInfo + information about git commit, operating system, etc. 68 /// Server version information. Usually VersionInfo + information about git commit, operating system, etc.
67 /// </summary> 69 /// </summary>
@@ -76,6 +78,11 @@ namespace OpenSim.Framework.Servers
76 78
77 protected void CreatePIDFile(string path) 79 protected void CreatePIDFile(string path)
78 { 80 {
81 if (File.Exists(path))
82 m_log.ErrorFormat(
83 "[SERVER BASE]: Previous pid file {0} still exists on startup. Possibly previously unclean shutdown.",
84 path);
85
79 try 86 try
80 { 87 {
81 string pidstring = System.Diagnostics.Process.GetCurrentProcess().Id.ToString(); 88 string pidstring = System.Diagnostics.Process.GetCurrentProcess().Id.ToString();
@@ -239,7 +246,7 @@ namespace OpenSim.Framework.Servers
239 "Show thread status", HandleShow); 246 "Show thread status", HandleShow);
240 247
241 m_console.Commands.AddCommand( 248 m_console.Commands.AddCommand(
242 "General", false, "threads abort", 249 "Debug", false, "threads abort",
243 "threads abort <thread-id>", 250 "threads abort <thread-id>",
244 "Abort a managed thread. Use \"show threads\" to find possible threads.", HandleThreadsAbort); 251 "Abort a managed thread. Use \"show threads\" to find possible threads.", HandleThreadsAbort);
245 252
@@ -249,11 +256,180 @@ namespace OpenSim.Framework.Servers
249 "Show thread status. Synonym for \"show threads\"", 256 "Show thread status. Synonym for \"show threads\"",
250 (string module, string[] args) => Notice(GetThreadsReport())); 257 (string module, string[] args) => Notice(GetThreadsReport()));
251 258
259 m_console.Commands.AddCommand (
260 "Debug", false, "debug comms set",
261 "debug comms set serialosdreq true|false",
262 "Set comms parameters. For debug purposes.",
263 HandleDebugCommsSet);
264
265 m_console.Commands.AddCommand (
266 "Debug", false, "debug comms status",
267 "debug comms status",
268 "Show current debug comms parameters.",
269 HandleDebugCommsStatus);
270
271 m_console.Commands.AddCommand (
272 "Debug", false, "debug threadpool set",
273 "debug threadpool set worker|iocp min|max <n>",
274 "Set threadpool parameters. For debug purposes.",
275 HandleDebugThreadpoolSet);
276
277 m_console.Commands.AddCommand (
278 "Debug", false, "debug threadpool status",
279 "debug threadpool status",
280 "Show current debug threadpool parameters.",
281 HandleDebugThreadpoolStatus);
282
252 m_console.Commands.AddCommand( 283 m_console.Commands.AddCommand(
253 "General", false, "force gc", 284 "Debug", false, "force gc",
254 "force gc", 285 "force gc",
255 "Manually invoke runtime garbage collection. For debugging purposes", 286 "Manually invoke runtime garbage collection. For debugging purposes",
256 HandleForceGc); 287 HandleForceGc);
288
289 m_console.Commands.AddCommand(
290 "General", false, "quit",
291 "quit",
292 "Quit the application", (mod, args) => Shutdown());
293
294 m_console.Commands.AddCommand(
295 "General", false, "shutdown",
296 "shutdown",
297 "Quit the application", (mod, args) => Shutdown());
298
299 ChecksManager.RegisterConsoleCommands(m_console);
300 StatsManager.RegisterConsoleCommands(m_console);
301 }
302
303 public void RegisterCommonComponents(IConfigSource configSource)
304 {
305 IConfig networkConfig = configSource.Configs["Network"];
306
307 if (networkConfig != null)
308 {
309 WebUtil.SerializeOSDRequestsPerEndpoint = networkConfig.GetBoolean("SerializeOSDRequests", false);
310 }
311
312 m_serverStatsCollector = new ServerStatsCollector();
313 m_serverStatsCollector.Initialise(configSource);
314 m_serverStatsCollector.Start();
315 }
316
317 private void HandleDebugCommsStatus(string module, string[] args)
318 {
319 Notice("serialosdreq is {0}", WebUtil.SerializeOSDRequestsPerEndpoint);
320 }
321
322 private void HandleDebugCommsSet(string module, string[] args)
323 {
324 if (args.Length != 5)
325 {
326 Notice("Usage: debug comms set serialosdreq true|false");
327 return;
328 }
329
330 if (args[3] != "serialosdreq")
331 {
332 Notice("Usage: debug comms set serialosdreq true|false");
333 return;
334 }
335
336 bool setSerializeOsdRequests;
337
338 if (!ConsoleUtil.TryParseConsoleBool(m_console, args[4], out setSerializeOsdRequests))
339 return;
340
341 WebUtil.SerializeOSDRequestsPerEndpoint = setSerializeOsdRequests;
342
343 Notice("serialosdreq is now {0}", setSerializeOsdRequests);
344 }
345
346 private void HandleDebugThreadpoolStatus(string module, string[] args)
347 {
348 int workerThreads, iocpThreads;
349
350 ThreadPool.GetMinThreads(out workerThreads, out iocpThreads);
351 Notice("Min worker threads: {0}", workerThreads);
352 Notice("Min IOCP threads: {0}", iocpThreads);
353
354 ThreadPool.GetMaxThreads(out workerThreads, out iocpThreads);
355 Notice("Max worker threads: {0}", workerThreads);
356 Notice("Max IOCP threads: {0}", iocpThreads);
357
358 ThreadPool.GetAvailableThreads(out workerThreads, out iocpThreads);
359 Notice("Available worker threads: {0}", workerThreads);
360 Notice("Available IOCP threads: {0}", iocpThreads);
361 }
362
363 private void HandleDebugThreadpoolSet(string module, string[] args)
364 {
365 if (args.Length != 6)
366 {
367 Notice("Usage: debug threadpool set worker|iocp min|max <n>");
368 return;
369 }
370
371 int newThreads;
372
373 if (!ConsoleUtil.TryParseConsoleInt(m_console, args[5], out newThreads))
374 return;
375
376 string poolType = args[3];
377 string bound = args[4];
378
379 bool fail = false;
380 int workerThreads, iocpThreads;
381
382 if (poolType == "worker")
383 {
384 if (bound == "min")
385 {
386 ThreadPool.GetMinThreads(out workerThreads, out iocpThreads);
387
388 if (!ThreadPool.SetMinThreads(newThreads, iocpThreads))
389 fail = true;
390 }
391 else
392 {
393 ThreadPool.GetMaxThreads(out workerThreads, out iocpThreads);
394
395 if (!ThreadPool.SetMaxThreads(newThreads, iocpThreads))
396 fail = true;
397 }
398 }
399 else
400 {
401 if (bound == "min")
402 {
403 ThreadPool.GetMinThreads(out workerThreads, out iocpThreads);
404
405 if (!ThreadPool.SetMinThreads(workerThreads, newThreads))
406 fail = true;
407 }
408 else
409 {
410 ThreadPool.GetMaxThreads(out workerThreads, out iocpThreads);
411
412 if (!ThreadPool.SetMaxThreads(workerThreads, newThreads))
413 fail = true;
414 }
415 }
416
417 if (fail)
418 {
419 Notice("ERROR: Could not set {0} {1} threads to {2}", poolType, bound, newThreads);
420 }
421 else
422 {
423 int minWorkerThreads, maxWorkerThreads, minIocpThreads, maxIocpThreads;
424
425 ThreadPool.GetMinThreads(out minWorkerThreads, out minIocpThreads);
426 ThreadPool.GetMaxThreads(out maxWorkerThreads, out maxIocpThreads);
427
428 Notice("Min worker threads now {0}", minWorkerThreads);
429 Notice("Min IOCP threads now {0}", minIocpThreads);
430 Notice("Max worker threads now {0}", maxWorkerThreads);
431 Notice("Max IOCP threads now {0}", maxIocpThreads);
432 }
257 } 433 }
258 434
259 private void HandleForceGc(string module, string[] args) 435 private void HandleForceGc(string module, string[] args)
@@ -641,7 +817,68 @@ namespace OpenSim.Framework.Servers
641 sb.AppendFormat("Total threads active: {0}\n\n", totalThreads); 817 sb.AppendFormat("Total threads active: {0}\n\n", totalThreads);
642 818
643 sb.Append("Main threadpool (excluding script engine pools)\n"); 819 sb.Append("Main threadpool (excluding script engine pools)\n");
644 sb.Append(Util.GetThreadPoolReport()); 820 sb.Append(GetThreadPoolReport());
821
822 return sb.ToString();
823 }
824
825 /// <summary>
826 /// Get a thread pool report.
827 /// </summary>
828 /// <returns></returns>
829 public static string GetThreadPoolReport()
830 {
831 string threadPoolUsed = null;
832 int maxThreads = 0;
833 int minThreads = 0;
834 int allocatedThreads = 0;
835 int inUseThreads = 0;
836 int waitingCallbacks = 0;
837 int completionPortThreads = 0;
838
839 StringBuilder sb = new StringBuilder();
840 if (Util.FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool)
841 {
842 STPInfo stpi = Util.GetSmartThreadPoolInfo();
843
844 // ROBUST currently leaves this the FireAndForgetMethod but never actually initializes the threadpool.
845 if (stpi != null)
846 {
847 threadPoolUsed = "SmartThreadPool";
848 maxThreads = stpi.MaxThreads;
849 minThreads = stpi.MinThreads;
850 inUseThreads = stpi.InUseThreads;
851 allocatedThreads = stpi.ActiveThreads;
852 waitingCallbacks = stpi.WaitingCallbacks;
853 }
854 }
855 else if (
856 Util.FireAndForgetMethod == FireAndForgetMethod.QueueUserWorkItem
857 || Util.FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem)
858 {
859 threadPoolUsed = "BuiltInThreadPool";
860 ThreadPool.GetMaxThreads(out maxThreads, out completionPortThreads);
861 ThreadPool.GetMinThreads(out minThreads, out completionPortThreads);
862 int availableThreads;
863 ThreadPool.GetAvailableThreads(out availableThreads, out completionPortThreads);
864 inUseThreads = maxThreads - availableThreads;
865 allocatedThreads = -1;
866 waitingCallbacks = -1;
867 }
868
869 if (threadPoolUsed != null)
870 {
871 sb.AppendFormat("Thread pool used : {0}\n", threadPoolUsed);
872 sb.AppendFormat("Max threads : {0}\n", maxThreads);
873 sb.AppendFormat("Min threads : {0}\n", minThreads);
874 sb.AppendFormat("Allocated threads : {0}\n", allocatedThreads < 0 ? "not applicable" : allocatedThreads.ToString());
875 sb.AppendFormat("In use threads : {0}\n", inUseThreads);
876 sb.AppendFormat("Work items waiting : {0}\n", waitingCallbacks < 0 ? "not available" : waitingCallbacks.ToString());
877 }
878 else
879 {
880 sb.AppendFormat("Thread pool not used\n");
881 }
645 882
646 return sb.ToString(); 883 return sb.ToString();
647 } 884 }
@@ -693,5 +930,16 @@ namespace OpenSim.Framework.Servers
693 if (m_console != null) 930 if (m_console != null)
694 m_console.OutputFormat(format, components); 931 m_console.OutputFormat(format, components);
695 } 932 }
933
934 public virtual void Shutdown()
935 {
936 m_serverStatsCollector.Close();
937 ShutdownSpecific();
938 }
939
940 /// <summary>
941 /// Should be overriden and referenced by descendents if they need to perform extra shutdown processing
942 /// </summary>
943 protected virtual void ShutdownSpecific() {}
696 } 944 }
697} 945}
diff --git a/OpenSim/Framework/Servers/VersionInfo.cs b/OpenSim/Framework/Servers/VersionInfo.cs
index 737c14d..33b1366 100644
--- a/OpenSim/Framework/Servers/VersionInfo.cs
+++ b/OpenSim/Framework/Servers/VersionInfo.cs
@@ -29,7 +29,7 @@ namespace OpenSim
29{ 29{
30 public class VersionInfo 30 public class VersionInfo
31 { 31 {
32 private const string VERSION_NUMBER = "0.7.6CM"; 32 private const string VERSION_NUMBER = "0.8.0CM";
33 private const Flavour VERSION_FLAVOUR = Flavour.Dev; 33 private const Flavour VERSION_FLAVOUR = Flavour.Dev;
34 34
35 public enum Flavour 35 public enum Flavour
diff --git a/OpenSim/Framework/TaskInventoryItem.cs b/OpenSim/Framework/TaskInventoryItem.cs
index 574ee56..2ec4bd1 100644
--- a/OpenSim/Framework/TaskInventoryItem.cs
+++ b/OpenSim/Framework/TaskInventoryItem.cs
@@ -124,7 +124,7 @@ namespace OpenSim.Framework
124 { 124 {
125 get 125 get
126 { 126 {
127 if (_creatorData != null && _creatorData != string.Empty) 127 if (!string.IsNullOrEmpty(_creatorData))
128 return _creatorID.ToString() + ';' + _creatorData; 128 return _creatorID.ToString() + ';' + _creatorData;
129 else 129 else
130 return _creatorID.ToString(); 130 return _creatorID.ToString();
diff --git a/OpenSim/Framework/Tests/LocationTest.cs b/OpenSim/Framework/Tests/LocationTest.cs
index a56ecb4..3d5d1d2 100644
--- a/OpenSim/Framework/Tests/LocationTest.cs
+++ b/OpenSim/Framework/Tests/LocationTest.cs
@@ -51,21 +51,28 @@ namespace OpenSim.Framework.Tests
51 [Test] 51 [Test]
52 public void locationXYRegionHandle() 52 public void locationXYRegionHandle()
53 { 53 {
54 Location TestLocation1 = new Location(256000,256000); 54 Location TestLocation1 = new Location(255000,256000);
55 Location TestLocation2 = new Location(1099511628032000); 55 Location TestLocation2 = new Location(1095216660736000);
56 Assert.That(TestLocation1 == TestLocation2); 56 Assert.That(TestLocation1 == TestLocation2);
57 57
58 Assert.That(TestLocation2.X == 256000 && TestLocation2.Y == 256000, "Test xy location doesn't match regionhandle provided"); 58 Assert.That(TestLocation1.X == 255000 && TestLocation1.Y == 256000, "Test xy location doesn't match position in the constructor");
59 Assert.That(TestLocation2.X == 255000 && TestLocation2.Y == 256000, "Test xy location doesn't match regionhandle provided");
59 60
60 Assert.That(TestLocation2.RegionHandle == 1099511628032000, 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");
63 66
64 TestLocation1 = new Location(256001, 256001); 67 TestLocation2 = new Location(RegionHandle);
65 TestLocation2 = new Location(1099511628032000); 68 Assert.That(TestLocation2.Equals(255000, 256000), "Decoded regionhandle failed to match the original position in the constructor");
69
70
71 TestLocation1 = new Location(255001, 256001);
72 TestLocation2 = new Location(1095216660736000);
66 Assert.That(TestLocation1 != TestLocation2); 73 Assert.That(TestLocation1 != TestLocation2);
67 74
68 Assert.That(TestLocation1.Equals(256001, 256001), "Equals(x,y) failed to match the position in the constructor"); 75 Assert.That(TestLocation1.Equals(255001, 256001), "Equals(x,y) failed to match the position in the constructor");
69 76
70 Assert.That(TestLocation2.GetHashCode() == (TestLocation2.X.GetHashCode() ^ TestLocation2.Y.GetHashCode()), "GetHashCode failed to produce the expected hashcode"); 77 Assert.That(TestLocation2.GetHashCode() == (TestLocation2.X.GetHashCode() ^ TestLocation2.Y.GetHashCode()), "GetHashCode failed to produce the expected hashcode");
71 78
diff --git a/OpenSim/Framework/Tests/MundaneFrameworkTests.cs b/OpenSim/Framework/Tests/MundaneFrameworkTests.cs
index 0fbdaf3..08f2af5 100644
--- a/OpenSim/Framework/Tests/MundaneFrameworkTests.cs
+++ b/OpenSim/Framework/Tests/MundaneFrameworkTests.cs
@@ -100,7 +100,7 @@ namespace OpenSim.Framework.Tests
100 cadu.AVHeight = Size1.Z; 100 cadu.AVHeight = Size1.Z;
101 101
102 AgentPosition position2 = new AgentPosition(); 102 AgentPosition position2 = new AgentPosition();
103 position2.CopyFrom(cadu); 103 position2.CopyFrom(cadu, position1.SessionID);
104 104
105 Assert.IsTrue( 105 Assert.IsTrue(
106 position2.AgentID == position1.AgentID 106 position2.AgentID == position1.AgentID
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/UserProfiles.cs b/OpenSim/Framework/UserProfiles.cs
new file mode 100644
index 0000000..6133591
--- /dev/null
+++ b/OpenSim/Framework/UserProfiles.cs
@@ -0,0 +1,117 @@
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 OpenMetaverse;
30
31namespace OpenSim.Framework
32{
33 public class UserClassifiedAdd
34 {
35 public UUID ClassifiedId = UUID.Zero;
36 public UUID CreatorId = UUID.Zero;
37 public int CreationDate = 0;
38 public int ExpirationDate = 0;
39 public int Category = 0;
40 public string Name = string.Empty;
41 public string Description = string.Empty;
42 public UUID ParcelId = UUID.Zero;
43 public int ParentEstate = 0;
44 public UUID SnapshotId = UUID.Zero;
45 public string SimName = string.Empty;
46 public string GlobalPos = "<0,0,0>";
47 public string ParcelName = string.Empty;
48 public byte Flags = 0;
49 public int Price = 0;
50 }
51
52 public class UserProfileProperties
53 {
54 public UUID UserId = UUID.Zero;
55 public UUID PartnerId = UUID.Zero;
56 public bool PublishProfile = false;
57 public bool PublishMature = false;
58 public string WebUrl = string.Empty;
59 public int WantToMask = 0;
60 public string WantToText = string.Empty;
61 public int SkillsMask = 0;
62 public string SkillsText = string.Empty;
63 public string Language = string.Empty;
64 public UUID ImageId = UUID.Zero;
65 public string AboutText = string.Empty;
66 public UUID FirstLifeImageId = UUID.Zero;
67 public string FirstLifeText = string.Empty;
68 }
69
70 public class UserProfilePick
71 {
72 public UUID PickId = UUID.Zero;
73 public UUID CreatorId = UUID.Zero;
74 public bool TopPick = false;
75 public string Name = string.Empty;
76 public string OriginalName = string.Empty;
77 public string Desc = string.Empty;
78 public UUID ParcelId = UUID.Zero;
79 public UUID SnapshotId = UUID.Zero;
80 public string User = string.Empty;
81 public string SimName = string.Empty;
82 public string GlobalPos = "<0,0,0>";
83 public int SortOrder = 0;
84 public bool Enabled = false;
85 }
86
87 public class UserProfileNotes
88 {
89 public UUID UserId;
90 public UUID TargetId;
91 public string Notes;
92 }
93
94 public class UserAccountProperties
95 {
96 public string EmailAddress = string.Empty;
97 public string Firstname = string.Empty;
98 public string LastName = string.Empty;
99 public string Password = string.Empty;
100 public string UserId = string.Empty;
101 }
102
103 public class UserAccountAuth
104 {
105 public string UserId = UUID.Zero.ToString();
106 public string Password = string.Empty;
107 }
108
109 public class UserAppData
110 {
111 public string TagId = string.Empty;
112 public string DataKey = string.Empty;
113 public string UserId = UUID.Zero.ToString();
114 public string DataVal = string.Empty;
115 }
116}
117
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs
index 557f38e..1775fef 100644
--- a/OpenSim/Framework/Util.cs
+++ b/OpenSim/Framework/Util.cs
@@ -89,9 +89,30 @@ namespace OpenSim.Framework
89 } 89 }
90 90
91 /// <summary> 91 /// <summary>
92 /// Class for delivering SmartThreadPool statistical information
93 /// </summary>
94 /// <remarks>
95 /// We do it this way so that we do not directly expose STP.
96 /// </remarks>
97 public class STPInfo
98 {
99 public string Name { get; set; }
100 public STPStartInfo STPStartInfo { get; set; }
101 public WIGStartInfo WIGStartInfo { get; set; }
102 public bool IsIdle { get; set; }
103 public bool IsShuttingDown { get; set; }
104 public int MaxThreads { get; set; }
105 public int MinThreads { get; set; }
106 public int InUseThreads { get; set; }
107 public int ActiveThreads { get; set; }
108 public int WaitingCallbacks { get; set; }
109 public int MaxConcurrentWorkItems { get; set; }
110 }
111
112 /// <summary>
92 /// Miscellaneous utility functions 113 /// Miscellaneous utility functions
93 /// </summary> 114 /// </summary>
94 public class Util 115 public static class Util
95 { 116 {
96 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 117 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
97 118
@@ -109,7 +130,7 @@ namespace OpenSim.Framework
109 private static SmartThreadPool m_ThreadPool; 130 private static SmartThreadPool m_ThreadPool;
110 131
111 // Unix-epoch starts at January 1st 1970, 00:00:00 UTC. And all our times in the server are (or at least should be) in UTC. 132 // Unix-epoch starts at January 1st 1970, 00:00:00 UTC. And all our times in the server are (or at least should be) in UTC.
112 private static readonly DateTime unixEpoch = 133 public static readonly DateTime UnixEpoch =
113 DateTime.ParseExact("1970-01-01 00:00:00 +0", "yyyy-MM-dd hh:mm:ss z", DateTimeFormatInfo.InvariantInfo).ToUniversalTime(); 134 DateTime.ParseExact("1970-01-01 00:00:00 +0", "yyyy-MM-dd hh:mm:ss z", DateTimeFormatInfo.InvariantInfo).ToUniversalTime();
114 135
115 private static readonly string rawUUIDPattern 136 private static readonly string rawUUIDPattern
@@ -120,6 +141,11 @@ namespace OpenSim.Framework
120 public static FireAndForgetMethod DefaultFireAndForgetMethod = FireAndForgetMethod.SmartThreadPool; 141 public static FireAndForgetMethod DefaultFireAndForgetMethod = FireAndForgetMethod.SmartThreadPool;
121 public static FireAndForgetMethod FireAndForgetMethod = DefaultFireAndForgetMethod; 142 public static FireAndForgetMethod FireAndForgetMethod = DefaultFireAndForgetMethod;
122 143
144 public static bool IsPlatformMono
145 {
146 get { return Type.GetType("Mono.Runtime") != null; }
147 }
148
123 /// <summary> 149 /// <summary>
124 /// Gets the name of the directory where the current running executable 150 /// Gets the name of the directory where the current running executable
125 /// is located 151 /// is located
@@ -307,6 +333,49 @@ namespace OpenSim.Framework
307 return Utils.UIntsToLong(X, Y); 333 return Utils.UIntsToLong(X, Y);
308 } 334 }
309 335
336 // Regions are identified with a 'handle' made up of its region coordinates packed into a ulong.
337 // Several places rely on the ability to extract a region's location from its handle.
338 // Note the location is in 'world coordinates' (see below).
339 // Region handles are based on the lowest coordinate of the region so trim the passed x,y to be the regions 0,0.
340 public static ulong RegionWorldLocToHandle(uint X, uint Y)
341 {
342 return Utils.UIntsToLong(X, Y);
343 }
344
345 public static ulong RegionLocToHandle(uint X, uint Y)
346 {
347 return Utils.UIntsToLong(Util.RegionToWorldLoc(X), Util.RegionToWorldLoc(Y));
348 }
349
350 public static void RegionHandleToWorldLoc(ulong handle, out uint X, out uint Y)
351 {
352 X = (uint)(handle >> 32);
353 Y = (uint)(handle & (ulong)uint.MaxValue);
354 }
355
356 public static void RegionHandleToRegionLoc(ulong handle, out uint X, out uint Y)
357 {
358 uint worldX, worldY;
359 RegionHandleToWorldLoc(handle, out worldX, out worldY);
360 X = WorldToRegionLoc(worldX);
361 Y = WorldToRegionLoc(worldY);
362 }
363
364 // A region location can be 'world coordinates' (meters from zero) or 'region coordinates'
365 // (number of regions from zero). This measurement of regions relies on the legacy 256 region size.
366 // These routines exist to make what is being converted explicit so the next person knows what was meant.
367 // Convert a region's 'world coordinate' to its 'region coordinate'.
368 public static uint WorldToRegionLoc(uint worldCoord)
369 {
370 return worldCoord / Constants.RegionSize;
371 }
372
373 // Convert a region's 'region coordinate' to its 'world coordinate'.
374 public static uint RegionToWorldLoc(uint regionCoord)
375 {
376 return regionCoord * Constants.RegionSize;
377 }
378
310 public static T Clamp<T>(T x, T min, T max) 379 public static T Clamp<T>(T x, T min, T max)
311 where T : IComparable<T> 380 where T : IComparable<T>
312 { 381 {
@@ -495,20 +564,18 @@ namespace OpenSim.Framework
495 564
496 public static int ToUnixTime(DateTime stamp) 565 public static int ToUnixTime(DateTime stamp)
497 { 566 {
498 TimeSpan t = stamp.ToUniversalTime() - unixEpoch; 567 TimeSpan t = stamp.ToUniversalTime() - UnixEpoch;
499 return (int) t.TotalSeconds; 568 return (int)t.TotalSeconds;
500 } 569 }
501 570
502 public static DateTime ToDateTime(ulong seconds) 571 public static DateTime ToDateTime(ulong seconds)
503 { 572 {
504 DateTime epoch = unixEpoch; 573 return UnixEpoch.AddSeconds(seconds);
505 return epoch.AddSeconds(seconds);
506 } 574 }
507 575
508 public static DateTime ToDateTime(int seconds) 576 public static DateTime ToDateTime(int seconds)
509 { 577 {
510 DateTime epoch = unixEpoch; 578 return UnixEpoch.AddSeconds(seconds);
511 return epoch.AddSeconds(seconds);
512 } 579 }
513 580
514 /// <summary> 581 /// <summary>
@@ -976,7 +1043,7 @@ namespace OpenSim.Framework
976 else if (typeof(T) == typeof(Int32)) 1043 else if (typeof(T) == typeof(Int32))
977 val = cnf.GetInt(varname, (int)val); 1044 val = cnf.GetInt(varname, (int)val);
978 else if (typeof(T) == typeof(float)) 1045 else if (typeof(T) == typeof(float))
979 val = cnf.GetFloat(varname, (int)val); 1046 val = cnf.GetFloat(varname, (float)val);
980 else 1047 else
981 m_log.ErrorFormat("[UTIL]: Unhandled type {0}", typeof(T)); 1048 m_log.ErrorFormat("[UTIL]: Unhandled type {0}", typeof(T));
982 } 1049 }
@@ -1233,7 +1300,7 @@ namespace OpenSim.Framework
1233 byte[] bytes = 1300 byte[] bytes =
1234 { 1301 {
1235 (byte)regionHandle, (byte)(regionHandle >> 8), (byte)(regionHandle >> 16), (byte)(regionHandle >> 24), 1302 (byte)regionHandle, (byte)(regionHandle >> 8), (byte)(regionHandle >> 16), (byte)(regionHandle >> 24),
1236 (byte)(regionHandle >> 32), (byte)(regionHandle >> 40), (byte)(regionHandle >> 48), (byte)(regionHandle << 56), 1303 (byte)(regionHandle >> 32), (byte)(regionHandle >> 40), (byte)(regionHandle >> 48), (byte)(regionHandle >> 56),
1237 (byte)x, (byte)(x >> 8), 0, 0, 1304 (byte)x, (byte)(x >> 8), 0, 0,
1238 (byte)y, (byte)(y >> 8), 0, 0 }; 1305 (byte)y, (byte)(y >> 8), 0, 0 };
1239 return new UUID(bytes, 0); 1306 return new UUID(bytes, 0);
@@ -1244,7 +1311,7 @@ namespace OpenSim.Framework
1244 byte[] bytes = 1311 byte[] bytes =
1245 { 1312 {
1246 (byte)regionHandle, (byte)(regionHandle >> 8), (byte)(regionHandle >> 16), (byte)(regionHandle >> 24), 1313 (byte)regionHandle, (byte)(regionHandle >> 8), (byte)(regionHandle >> 16), (byte)(regionHandle >> 24),
1247 (byte)(regionHandle >> 32), (byte)(regionHandle >> 40), (byte)(regionHandle >> 48), (byte)(regionHandle << 56), 1314 (byte)(regionHandle >> 32), (byte)(regionHandle >> 40), (byte)(regionHandle >> 48), (byte)(regionHandle >> 56),
1248 (byte)x, (byte)(x >> 8), (byte)z, (byte)(z >> 8), 1315 (byte)x, (byte)(x >> 8), (byte)z, (byte)(z >> 8),
1249 (byte)y, (byte)(y >> 8), 0, 0 }; 1316 (byte)y, (byte)(y >> 8), 0, 0 };
1250 return new UUID(bytes, 0); 1317 return new UUID(bytes, 0);
@@ -1317,7 +1384,7 @@ namespace OpenSim.Framework
1317 ru = "OSX/Mono"; 1384 ru = "OSX/Mono";
1318 else 1385 else
1319 { 1386 {
1320 if (Type.GetType("Mono.Runtime") != null) 1387 if (IsPlatformMono)
1321 ru = "Win/Mono"; 1388 ru = "Win/Mono";
1322 else 1389 else
1323 ru = "Win/.NET"; 1390 ru = "Win/.NET";
@@ -1765,10 +1832,12 @@ namespace OpenSim.Framework
1765 FireAndForget(callback, null); 1832 FireAndForget(callback, null);
1766 } 1833 }
1767 1834
1768 public static void InitThreadPool(int maxThreads) 1835 public static void InitThreadPool(int minThreads, int maxThreads)
1769 { 1836 {
1770 if (maxThreads < 2) 1837 if (maxThreads < 2)
1771 throw new ArgumentOutOfRangeException("maxThreads", "maxThreads must be greater than 2"); 1838 throw new ArgumentOutOfRangeException("maxThreads", "maxThreads must be greater than 2");
1839 if (minThreads > maxThreads || minThreads < 2)
1840 throw new ArgumentOutOfRangeException("minThreads", "minThreads must be greater than 2 and less than or equal to maxThreads");
1772 if (m_ThreadPool != null) 1841 if (m_ThreadPool != null)
1773 throw new InvalidOperationException("SmartThreadPool is already initialized"); 1842 throw new InvalidOperationException("SmartThreadPool is already initialized");
1774 1843
@@ -1776,7 +1845,7 @@ namespace OpenSim.Framework
1776 startInfo.ThreadPoolName = "Util"; 1845 startInfo.ThreadPoolName = "Util";
1777 startInfo.IdleTimeout = 2000; 1846 startInfo.IdleTimeout = 2000;
1778 startInfo.MaxWorkerThreads = maxThreads; 1847 startInfo.MaxWorkerThreads = maxThreads;
1779 startInfo.MinWorkerThreads = 2; 1848 startInfo.MinWorkerThreads = minThreads;
1780 1849
1781 m_ThreadPool = new SmartThreadPool(startInfo); 1850 m_ThreadPool = new SmartThreadPool(startInfo);
1782 } 1851 }
@@ -1851,8 +1920,8 @@ namespace OpenSim.Framework
1851 break; 1920 break;
1852 case FireAndForgetMethod.SmartThreadPool: 1921 case FireAndForgetMethod.SmartThreadPool:
1853 if (m_ThreadPool == null) 1922 if (m_ThreadPool == null)
1854 InitThreadPool(15); 1923 InitThreadPool(2, 15);
1855 m_ThreadPool.QueueWorkItem(SmartThreadPoolCallback, new object[] { realCallback, obj }); 1924 m_ThreadPool.QueueWorkItem((cb, o) => cb(o), realCallback, obj);
1856 break; 1925 break;
1857 case FireAndForgetMethod.Thread: 1926 case FireAndForgetMethod.Thread:
1858 Thread thread = new Thread(delegate(object o) { realCallback(o); }); 1927 Thread thread = new Thread(delegate(object o) { realCallback(o); });
@@ -1864,72 +1933,29 @@ namespace OpenSim.Framework
1864 } 1933 }
1865 1934
1866 /// <summary> 1935 /// <summary>
1867 /// Get a thread pool report. 1936 /// Get information about the current state of the smart thread pool.
1868 /// </summary> 1937 /// </summary>
1869 /// <returns></returns> 1938 /// <returns>
1870 public static string GetThreadPoolReport() 1939 /// null if this isn't the pool being used for non-scriptengine threads.
1940 /// </returns>
1941 public static STPInfo GetSmartThreadPoolInfo()
1871 { 1942 {
1872 string threadPoolUsed = null; 1943 if (m_ThreadPool == null)
1873 int maxThreads = 0; 1944 return null;
1874 int minThreads = 0;
1875 int allocatedThreads = 0;
1876 int inUseThreads = 0;
1877 int waitingCallbacks = 0;
1878 int completionPortThreads = 0;
1879
1880 StringBuilder sb = new StringBuilder();
1881 if (FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool)
1882 {
1883 // ROBUST currently leaves this the FireAndForgetMethod but never actually initializes the threadpool.
1884 if (m_ThreadPool != null)
1885 {
1886 threadPoolUsed = "SmartThreadPool";
1887 maxThreads = m_ThreadPool.MaxThreads;
1888 minThreads = m_ThreadPool.MinThreads;
1889 inUseThreads = m_ThreadPool.InUseThreads;
1890 allocatedThreads = m_ThreadPool.ActiveThreads;
1891 waitingCallbacks = m_ThreadPool.WaitingCallbacks;
1892 }
1893 }
1894 else if (
1895 FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem
1896 || FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem)
1897 {
1898 threadPoolUsed = "BuiltInThreadPool";
1899 ThreadPool.GetMaxThreads(out maxThreads, out completionPortThreads);
1900 ThreadPool.GetMinThreads(out minThreads, out completionPortThreads);
1901 int availableThreads;
1902 ThreadPool.GetAvailableThreads(out availableThreads, out completionPortThreads);
1903 inUseThreads = maxThreads - availableThreads;
1904 allocatedThreads = -1;
1905 waitingCallbacks = -1;
1906 }
1907
1908 if (threadPoolUsed != null)
1909 {
1910 sb.AppendFormat("Thread pool used : {0}\n", threadPoolUsed);
1911 sb.AppendFormat("Max threads : {0}\n", maxThreads);
1912 sb.AppendFormat("Min threads : {0}\n", minThreads);
1913 sb.AppendFormat("Allocated threads : {0}\n", allocatedThreads < 0 ? "not applicable" : allocatedThreads.ToString());
1914 sb.AppendFormat("In use threads : {0}\n", inUseThreads);
1915 sb.AppendFormat("Work items waiting : {0}\n", waitingCallbacks < 0 ? "not available" : waitingCallbacks.ToString());
1916 }
1917 else
1918 {
1919 sb.AppendFormat("Thread pool not used\n");
1920 }
1921
1922 return sb.ToString();
1923 }
1924 1945
1925 private static object SmartThreadPoolCallback(object o) 1946 STPInfo stpi = new STPInfo();
1926 { 1947 stpi.Name = m_ThreadPool.Name;
1927 object[] array = (object[])o; 1948 stpi.STPStartInfo = m_ThreadPool.STPStartInfo;
1928 WaitCallback callback = (WaitCallback)array[0]; 1949 stpi.IsIdle = m_ThreadPool.IsIdle;
1929 object obj = array[1]; 1950 stpi.IsShuttingDown = m_ThreadPool.IsShuttingdown;
1951 stpi.MaxThreads = m_ThreadPool.MaxThreads;
1952 stpi.MinThreads = m_ThreadPool.MinThreads;
1953 stpi.InUseThreads = m_ThreadPool.InUseThreads;
1954 stpi.ActiveThreads = m_ThreadPool.ActiveThreads;
1955 stpi.WaitingCallbacks = m_ThreadPool.WaitingCallbacks;
1956 stpi.MaxConcurrentWorkItems = m_ThreadPool.Concurrency;
1930 1957
1931 callback(obj); 1958 return stpi;
1932 return null;
1933 } 1959 }
1934 1960
1935 #endregion FireAndForget Threading Pattern 1961 #endregion FireAndForget Threading Pattern
@@ -2058,8 +2084,10 @@ namespace OpenSim.Framework
2058 #region Xml Serialization Utilities 2084 #region Xml Serialization Utilities
2059 public static bool ReadBoolean(XmlTextReader reader) 2085 public static bool ReadBoolean(XmlTextReader reader)
2060 { 2086 {
2087 // AuroraSim uses "int" for some fields that are boolean in OpenSim, e.g. "PassCollisions". Don't fail because of this.
2061 reader.ReadStartElement(); 2088 reader.ReadStartElement();
2062 bool result = Boolean.Parse(reader.ReadContentAsString().ToLower()); 2089 string val = reader.ReadContentAsString().ToLower();
2090 bool result = val.Equals("true") || val.Equals("1");
2063 reader.ReadEndElement(); 2091 reader.ReadEndElement();
2064 2092
2065 return result; 2093 return result;
@@ -2148,7 +2176,7 @@ namespace OpenSim.Framework
2148 /// <param name="secret">the secret part</param> 2176 /// <param name="secret">the secret part</param>
2149 public static bool ParseUniversalUserIdentifier(string value, out UUID uuid, out string url, out string firstname, out string lastname, out string secret) 2177 public static bool ParseUniversalUserIdentifier(string value, out UUID uuid, out string url, out string firstname, out string lastname, out string secret)
2150 { 2178 {
2151 uuid = UUID.Zero; url = string.Empty; firstname = "Unknown"; lastname = "User"; secret = string.Empty; 2179 uuid = UUID.Zero; url = string.Empty; firstname = "Unknown"; lastname = "UserUPUUI"; secret = string.Empty;
2152 2180
2153 string[] parts = value.Split(';'); 2181 string[] parts = value.Split(';');
2154 if (parts.Length >= 1) 2182 if (parts.Length >= 1)
@@ -2282,7 +2310,7 @@ namespace OpenSim.Framework
2282 { 2310 {
2283 lock (m_syncRoot) 2311 lock (m_syncRoot)
2284 { 2312 {
2285 m_lowQueue.Enqueue(data); 2313 q.Enqueue(data);
2286 m_s.WaitOne(0); 2314 m_s.WaitOne(0);
2287 m_s.Release(); 2315 m_s.Release();
2288 } 2316 }
@@ -2322,7 +2350,7 @@ namespace OpenSim.Framework
2322 { 2350 {
2323 if (m_highQueue.Count > 0) 2351 if (m_highQueue.Count > 0)
2324 res = m_highQueue.Dequeue(); 2352 res = m_highQueue.Dequeue();
2325 else 2353 else if (m_lowQueue.Count > 0)
2326 res = m_lowQueue.Dequeue(); 2354 res = m_lowQueue.Dequeue();
2327 2355
2328 if (m_highQueue.Count == 0 && m_lowQueue.Count == 0) 2356 if (m_highQueue.Count == 0 && m_lowQueue.Count == 0)
diff --git a/OpenSim/Framework/WebUtil.cs b/OpenSim/Framework/WebUtil.cs
index bf57fd4..33ef8e0 100644
--- a/OpenSim/Framework/WebUtil.cs
+++ b/OpenSim/Framework/WebUtil.cs
@@ -67,6 +67,11 @@ namespace OpenSim.Framework
67 public static int RequestNumber { get; internal set; } 67 public static int RequestNumber { get; internal set; }
68 68
69 /// <summary> 69 /// <summary>
70 /// Control where OSD requests should be serialized per endpoint.
71 /// </summary>
72 public static bool SerializeOSDRequestsPerEndpoint { get; set; }
73
74 /// <summary>
70 /// this is the header field used to communicate the local request id 75 /// this is the header field used to communicate the local request id
71 /// used for performance and debugging 76 /// used for performance and debugging
72 /// </summary> 77 /// </summary>
@@ -145,10 +150,50 @@ namespace OpenSim.Framework
145 150
146 public static OSDMap ServiceOSDRequest(string url, OSDMap data, string method, int timeout, bool compressed) 151 public static OSDMap ServiceOSDRequest(string url, OSDMap data, string method, int timeout, bool compressed)
147 { 152 {
148 lock (EndPointLock(url)) 153 if (SerializeOSDRequestsPerEndpoint)
154 {
155 lock (EndPointLock(url))
156 {
157 return ServiceOSDRequestWorker(url, data, method, timeout, compressed);
158 }
159 }
160 else
161 {
162 return ServiceOSDRequestWorker(url, data, method, timeout, compressed);
163 }
164 }
165
166 public static void LogOutgoingDetail(Stream outputStream)
167 {
168 using (StreamReader reader = new StreamReader(Util.Copy(outputStream), Encoding.UTF8))
169 {
170 string output;
171
172 if (DebugLevel == 5)
173 {
174 const int sampleLength = 80;
175 char[] sampleChars = new char[sampleLength];
176 reader.Read(sampleChars, 0, sampleLength);
177 output = new string(sampleChars);
178 }
179 else
180 {
181 output = reader.ReadToEnd();
182 }
183
184 LogOutgoingDetail(output);
185 }
186 }
187
188 public static void LogOutgoingDetail(string output)
189 {
190 if (DebugLevel == 5)
149 { 191 {
150 return ServiceOSDRequestWorker(url,data,method,timeout,compressed); 192 output = output.Substring(0, 80);
193 output = output + "...";
151 } 194 }
195
196 m_log.DebugFormat("[WEB UTIL]: {0}", output.Replace("\n", @"\n"));
152 } 197 }
153 198
154 private static OSDMap ServiceOSDRequestWorker(string url, OSDMap data, string method, int timeout, bool compressed) 199 private static OSDMap ServiceOSDRequestWorker(string url, OSDMap data, string method, int timeout, bool compressed)
@@ -178,7 +223,11 @@ namespace OpenSim.Framework
178 // If there is some input, write it into the request 223 // If there is some input, write it into the request
179 if (data != null) 224 if (data != null)
180 { 225 {
181 strBuffer = OSDParser.SerializeJsonString(data); 226 strBuffer = OSDParser.SerializeJsonString(data);
227
228 if (DebugLevel >= 5)
229 LogOutgoingDetail(strBuffer);
230
182 byte[] buffer = System.Text.Encoding.UTF8.GetBytes(strBuffer); 231 byte[] buffer = System.Text.Encoding.UTF8.GetBytes(strBuffer);
183 232
184 if (compressed) 233 if (compressed)
@@ -358,6 +407,10 @@ namespace OpenSim.Framework
358 if (data != null) 407 if (data != null)
359 { 408 {
360 queryString = BuildQueryString(data); 409 queryString = BuildQueryString(data);
410
411 if (DebugLevel >= 5)
412 LogOutgoingDetail(queryString);
413
361 byte[] buffer = System.Text.Encoding.UTF8.GetBytes(queryString); 414 byte[] buffer = System.Text.Encoding.UTF8.GetBytes(queryString);
362 415
363 request.ContentLength = buffer.Length; 416 request.ContentLength = buffer.Length;
@@ -668,7 +721,7 @@ namespace OpenSim.Framework
668 /// <returns></returns> 721 /// <returns></returns>
669 public static string[] GetPreferredImageTypes(string accept) 722 public static string[] GetPreferredImageTypes(string accept)
670 { 723 {
671 if (accept == null || accept == string.Empty) 724 if (string.IsNullOrEmpty(accept))
672 return new string[0]; 725 return new string[0];
673 726
674 string[] types = accept.Split(new char[] { ',' }); 727 string[] types = accept.Split(new char[] { ',' });
@@ -769,6 +822,9 @@ namespace OpenSim.Framework
769 int length = (int)buffer.Length; 822 int length = (int)buffer.Length;
770 request.ContentLength = length; 823 request.ContentLength = length;
771 824
825 if (WebUtil.DebugLevel >= 5)
826 WebUtil.LogOutgoingDetail(buffer);
827
772 request.BeginGetRequestStream(delegate(IAsyncResult res) 828 request.BeginGetRequestStream(delegate(IAsyncResult res)
773 { 829 {
774 Stream requestStream = request.EndGetRequestStream(res); 830 Stream requestStream = request.EndGetRequestStream(res);
@@ -928,11 +984,12 @@ namespace OpenSim.Framework
928 /// <param name="verb"></param> 984 /// <param name="verb"></param>
929 /// <param name="requestUrl"></param> 985 /// <param name="requestUrl"></param>
930 /// <param name="obj"> </param> 986 /// <param name="obj"> </param>
987 /// <param name="timeoutsecs"> </param>
931 /// <returns></returns> 988 /// <returns></returns>
932 /// 989 ///
933 /// <exception cref="System.Net.WebException">Thrown if we encounter a network issue while posting 990 /// <exception cref="System.Net.WebException">Thrown if we encounter a network issue while posting
934 /// the request. You'll want to make sure you deal with this as they're not uncommon</exception> 991 /// the request. You'll want to make sure you deal with this as they're not uncommon</exception>
935 public static string MakeRequest(string verb, string requestUrl, string obj) 992 public static string MakeRequest(string verb, string requestUrl, string obj, int timeoutsecs)
936 { 993 {
937 int reqnum = WebUtil.RequestNumber++; 994 int reqnum = WebUtil.RequestNumber++;
938 995
@@ -946,6 +1003,8 @@ namespace OpenSim.Framework
946 1003
947 WebRequest request = WebRequest.Create(requestUrl); 1004 WebRequest request = WebRequest.Create(requestUrl);
948 request.Method = verb; 1005 request.Method = verb;
1006 if (timeoutsecs > 0)
1007 request.Timeout = timeoutsecs * 1000;
949 string respstring = String.Empty; 1008 string respstring = String.Empty;
950 1009
951 int tickset = Util.EnvironmentTickCountSubtract(tickstart); 1010 int tickset = Util.EnvironmentTickCountSubtract(tickstart);
@@ -966,6 +1025,9 @@ namespace OpenSim.Framework
966 length = (int)obj.Length; 1025 length = (int)obj.Length;
967 request.ContentLength = length; 1026 request.ContentLength = length;
968 1027
1028 if (WebUtil.DebugLevel >= 5)
1029 WebUtil.LogOutgoingDetail(buffer);
1030
969 Stream requestStream = null; 1031 Stream requestStream = null;
970 try 1032 try
971 { 1033 {
@@ -1039,6 +1101,11 @@ namespace OpenSim.Framework
1039 1101
1040 return respstring; 1102 return respstring;
1041 } 1103 }
1104
1105 public static string MakeRequest(string verb, string requestUrl, string obj)
1106 {
1107 return MakeRequest(verb, requestUrl, obj, -1);
1108 }
1042 } 1109 }
1043 1110
1044 public class SynchronousRestObjectRequester 1111 public class SynchronousRestObjectRequester
@@ -1111,6 +1178,9 @@ namespace OpenSim.Framework
1111 int length = (int)buffer.Length; 1178 int length = (int)buffer.Length;
1112 request.ContentLength = length; 1179 request.ContentLength = length;
1113 1180
1181 if (WebUtil.DebugLevel >= 5)
1182 WebUtil.LogOutgoingDetail(buffer);
1183
1114 Stream requestStream = null; 1184 Stream requestStream = null;
1115 try 1185 try
1116 { 1186 {
@@ -1213,4 +1283,4 @@ namespace OpenSim.Framework
1213 return deserial; 1283 return deserial;
1214 } 1284 }
1215 } 1285 }
1216} 1286} \ No newline at end of file