aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Capabilities/Caps.cs93
-rw-r--r--OpenSim/Data/Null/NullSimulationData.cs20
-rw-r--r--OpenSim/Data/SQLite/Resources/HGTravelStore.migrations20
-rw-r--r--OpenSim/Framework/BlockingQueue.cs36
-rw-r--r--OpenSim/Framework/Console/RemoteConsole.cs2
-rw-r--r--OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs2
-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.cs4
-rw-r--r--OpenSim/Framework/Util.cs12
-rw-r--r--OpenSim/Region/Application/OpenSim.cs9
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs13
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs85
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs6
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs2
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs67
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs20
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs10
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs6
-rw-r--r--OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs92
-rw-r--r--OpenSim/Region/CoreModules/Framework/ServiceThrottle/ServiceThrottleModule.cs (renamed from OpenSim/Region/CoreModules/Framework/GridServiceThrottle/GridServiceThrottleModule.cs)169
-rw-r--r--OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs122
-rw-r--r--OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs6
-rw-r--r--OpenSim/Region/Framework/Interfaces/IServiceThrottleModule.cs19
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs6
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs17
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs8
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs13
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs3
-rw-r--r--OpenSim/Region/RegionCombinerModule/RegionCombinerIndividualEventForwarder.cs6
30 files changed, 653 insertions, 278 deletions
diff --git a/OpenSim/Capabilities/Caps.cs b/OpenSim/Capabilities/Caps.cs
index 95fc61b..30a323e 100644
--- a/OpenSim/Capabilities/Caps.cs
+++ b/OpenSim/Capabilities/Caps.cs
@@ -64,7 +64,11 @@ namespace OpenSim.Framework.Capabilities
64 public string CapsObjectPath { get { return m_capsObjectPath; } } 64 public string CapsObjectPath { get { return m_capsObjectPath; } }
65 65
66 private CapsHandlers m_capsHandlers; 66 private CapsHandlers m_capsHandlers;
67 private Dictionary<string, string> m_externalCapsHandlers; 67
68 private Dictionary<string, PollServiceEventArgs> m_pollServiceHandlers
69 = new Dictionary<string, PollServiceEventArgs>();
70
71 private Dictionary<string, string> m_externalCapsHandlers = new Dictionary<string, string>();
68 72
69 private IHttpServer m_httpListener; 73 private IHttpServer m_httpListener;
70 private UUID m_agentID; 74 private UUID m_agentID;
@@ -134,7 +138,6 @@ namespace OpenSim.Framework.Capabilities
134 138
135 m_agentID = agent; 139 m_agentID = agent;
136 m_capsHandlers = new CapsHandlers(httpServer, httpListen, httpPort, (httpServer == null) ? false : httpServer.UseSSL); 140 m_capsHandlers = new CapsHandlers(httpServer, httpListen, httpPort, (httpServer == null) ? false : httpServer.UseSSL);
137 m_externalCapsHandlers = new Dictionary<string, string>();
138 m_regionName = regionName; 141 m_regionName = regionName;
139 } 142 }
140 143
@@ -149,6 +152,27 @@ namespace OpenSim.Framework.Capabilities
149 m_capsHandlers[capName] = handler; 152 m_capsHandlers[capName] = handler;
150 } 153 }
151 154
155 public void RegisterPollHandler(string capName, PollServiceEventArgs pollServiceHandler)
156 {
157 m_pollServiceHandlers.Add(capName, pollServiceHandler);
158
159 m_httpListener.AddPollServiceHTTPHandler(pollServiceHandler.Url, pollServiceHandler);
160
161// uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port;
162// string protocol = "http";
163// string hostName = m_httpListenerHostName;
164//
165// if (MainServer.Instance.UseSSL)
166// {
167// hostName = MainServer.Instance.SSLCommonName;
168// port = MainServer.Instance.SSLPort;
169// protocol = "https";
170// }
171
172// RegisterHandler(
173// capName, String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, pollServiceHandler.Url));
174 }
175
152 /// <summary> 176 /// <summary>
153 /// Register an external handler. The service for this capability is somewhere else 177 /// Register an external handler. The service for this capability is somewhere else
154 /// given by the URL. 178 /// given by the URL.
@@ -165,13 +189,70 @@ namespace OpenSim.Framework.Capabilities
165 /// </summary> 189 /// </summary>
166 public void DeregisterHandlers() 190 public void DeregisterHandlers()
167 { 191 {
168 if (m_capsHandlers != null) 192 foreach (string capsName in m_capsHandlers.Caps)
193 {
194 m_capsHandlers.Remove(capsName);
195 }
196
197 foreach (PollServiceEventArgs handler in m_pollServiceHandlers.Values)
198 {
199 m_httpListener.RemovePollServiceHTTPHandler("", handler.Url);
200 }
201 }
202
203 public bool TryGetPollHandler(string name, out PollServiceEventArgs pollHandler)
204 {
205 return m_pollServiceHandlers.TryGetValue(name, out pollHandler);
206 }
207
208 public Dictionary<string, PollServiceEventArgs> GetPollHandlers()
209 {
210 return new Dictionary<string, PollServiceEventArgs>(m_pollServiceHandlers);
211 }
212
213 /// <summary>
214 /// Return an LLSD-serializable Hashtable describing the
215 /// capabilities and their handler details.
216 /// </summary>
217 /// <param name="excludeSeed">If true, then exclude the seed cap.</param>
218 public Hashtable GetCapsDetails(bool excludeSeed, List<string> requestedCaps)
219 {
220 Hashtable caps = CapsHandlers.GetCapsDetails(excludeSeed, requestedCaps);
221
222 lock (m_pollServiceHandlers)
169 { 223 {
170 foreach (string capsName in m_capsHandlers.Caps) 224 foreach (KeyValuePair <string, PollServiceEventArgs> kvp in m_pollServiceHandlers)
171 { 225 {
172 m_capsHandlers.Remove(capsName); 226 if (!requestedCaps.Contains(kvp.Key))
227 continue;
228
229 string hostName = m_httpListenerHostName;
230 uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port;
231 string protocol = "http";
232
233 if (MainServer.Instance.UseSSL)
234 {
235 hostName = MainServer.Instance.SSLCommonName;
236 port = MainServer.Instance.SSLPort;
237 protocol = "https";
238 }
239 //
240 // caps.RegisterHandler("FetchInventoryDescendents2", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl));
241
242 caps[kvp.Key] = string.Format("{0}://{1}:{2}{3}", protocol, hostName, port, kvp.Value.Url);
173 } 243 }
174 } 244 }
245
246 // Add the external too
247 foreach (KeyValuePair<string, string> kvp in ExternalCapsHandlers)
248 {
249 if (!requestedCaps.Contains(kvp.Key))
250 continue;
251
252 caps[kvp.Key] = kvp.Value;
253 }
254
255 return caps;
175 } 256 }
176 257
177 public void Activate() 258 public void Activate()
@@ -185,4 +266,4 @@ namespace OpenSim.Framework.Capabilities
185 return m_capsActive.WaitOne(30000); 266 return m_capsActive.WaitOne(30000);
186 } 267 }
187 } 268 }
188} 269} \ No newline at end of file
diff --git a/OpenSim/Data/Null/NullSimulationData.cs b/OpenSim/Data/Null/NullSimulationData.cs
index e7e5c41..15824a9 100644
--- a/OpenSim/Data/Null/NullSimulationData.cs
+++ b/OpenSim/Data/Null/NullSimulationData.cs
@@ -77,20 +77,34 @@ namespace OpenSim.Data.Null
77 } 77 }
78 78
79 #region Environment Settings 79 #region Environment Settings
80
81 private Dictionary<UUID, string> EnvironmentSettings = new Dictionary<UUID, string>();
82
80 public string LoadRegionEnvironmentSettings(UUID regionUUID) 83 public string LoadRegionEnvironmentSettings(UUID regionUUID)
81 { 84 {
82 //This connector doesn't support the Environment module yet 85 lock (EnvironmentSettings)
86 {
87 if (EnvironmentSettings.ContainsKey(regionUUID))
88 return EnvironmentSettings[regionUUID];
89 }
83 return string.Empty; 90 return string.Empty;
84 } 91 }
85 92
86 public void StoreRegionEnvironmentSettings(UUID regionUUID, string settings) 93 public void StoreRegionEnvironmentSettings(UUID regionUUID, string settings)
87 { 94 {
88 //This connector doesn't support the Environment module yet 95 lock (EnvironmentSettings)
96 {
97 EnvironmentSettings[regionUUID] = settings;
98 }
89 } 99 }
90 100
91 public void RemoveRegionEnvironmentSettings(UUID regionUUID) 101 public void RemoveRegionEnvironmentSettings(UUID regionUUID)
92 { 102 {
93 //This connector doesn't support the Environment module yet 103 lock (EnvironmentSettings)
104 {
105 if (EnvironmentSettings.ContainsKey(regionUUID))
106 EnvironmentSettings.Remove(regionUUID);
107 }
94 } 108 }
95 #endregion 109 #endregion
96 110
diff --git a/OpenSim/Data/SQLite/Resources/HGTravelStore.migrations b/OpenSim/Data/SQLite/Resources/HGTravelStore.migrations
index 2e73caa..02612ce 100644
--- a/OpenSim/Data/SQLite/Resources/HGTravelStore.migrations
+++ b/OpenSim/Data/SQLite/Resources/HGTravelStore.migrations
@@ -1,18 +1,18 @@
1:VERSION 1 # -------------------------- 1:VERSION 2 # --------------------------
2 2
3BEGIN; 3BEGIN;
4 4
5CREATE TABLE hg_traveling_data ( 5CREATE TABLE hg_traveling_data(
6 SessionID VARCHAR(36) NOT NULL, 6 SessionID VARCHAR(36) NOT NULL,
7 UserID VARCHAR(36) NOT NULL, 7 UserID VARCHAR(36) NOT NULL,
8 GridExternalName VARCHAR(255) NOT NULL DEFAULT '', 8 GridExternalName VARCHAR(255) NOT NULL DEFAULT "",
9 ServiceToken VARCHAR(255) NOT NULL DEFAULT '', 9 ServiceToken VARCHAR(255) NOT NULL DEFAULT "",
10 ClientIPAddress VARCHAR(16) NOT NULL DEFAULT '', 10 ClientIPAddress VARCHAR(16) NOT NULL DEFAULT "",
11 MyIPAddress VARCHAR(16) NOT NULL DEFAULT '', 11 MyIPAddress VARCHAR(16) NOT NULL DEFAULT "",
12 TMStamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 12 TMStamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
13 PRIMARY KEY (`SessionID`), 13 PRIMARY KEY(SessionID),
14 KEY (`UserID`) 14 UNIQUE(UserID)
15) ENGINE=InnoDB; 15);
16 16
17COMMIT; 17COMMIT;
18 18
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/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/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
index 0fde42c..f4b4156 100644
--- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
+++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
@@ -387,6 +387,8 @@ namespace OpenSim.Framework.Servers.HttpServer
387 387
388 if (TryGetPollServiceHTTPHandler(request.UriPath.ToString(), out psEvArgs)) 388 if (TryGetPollServiceHTTPHandler(request.UriPath.ToString(), out psEvArgs))
389 { 389 {
390 psEvArgs.RequestsReceived++;
391
390 PollServiceHttpRequest psreq = new PollServiceHttpRequest(psEvArgs, context, request); 392 PollServiceHttpRequest psreq = new PollServiceHttpRequest(psEvArgs, context, request);
391 393
392 if (psEvArgs.Request != null) 394 if (psEvArgs.Request != null)
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 98789be..44f7045 100644
--- a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
+++ b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
@@ -105,7 +105,7 @@ namespace OpenSim.Framework.Servers.HttpServer
105 { 105 {
106 if (m_running) 106 if (m_running)
107 { 107 {
108 if (req.PollServiceArgs.Type != PollServiceEventArgs.EventType.Normal) 108 if (req.PollServiceArgs.Type != PollServiceEventArgs.EventType.LongPoll)
109 { 109 {
110 m_requests.Enqueue(req); 110 m_requests.Enqueue(req);
111 } 111 }
@@ -207,7 +207,7 @@ namespace OpenSim.Framework.Servers.HttpServer
207 if (responsedata == null) 207 if (responsedata == null)
208 continue; 208 continue;
209 209
210 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
211 { 211 {
212 try 212 try
213 { 213 {
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs
index 6c7af12..19d40db 100644
--- a/OpenSim/Framework/Util.cs
+++ b/OpenSim/Framework/Util.cs
@@ -1791,10 +1791,12 @@ namespace OpenSim.Framework
1791 FireAndForget(callback, null); 1791 FireAndForget(callback, null);
1792 } 1792 }
1793 1793
1794 public static void InitThreadPool(int maxThreads) 1794 public static void InitThreadPool(int minThreads, int maxThreads)
1795 { 1795 {
1796 if (maxThreads < 2) 1796 if (maxThreads < 2)
1797 throw new ArgumentOutOfRangeException("maxThreads", "maxThreads must be greater than 2"); 1797 throw new ArgumentOutOfRangeException("maxThreads", "maxThreads must be greater than 2");
1798 if (minThreads > maxThreads || minThreads < 2)
1799 throw new ArgumentOutOfRangeException("minThreads", "minThreads must be greater than 2 and less than or equal to maxThreads");
1798 if (m_ThreadPool != null) 1800 if (m_ThreadPool != null)
1799 throw new InvalidOperationException("SmartThreadPool is already initialized"); 1801 throw new InvalidOperationException("SmartThreadPool is already initialized");
1800 1802
@@ -1802,7 +1804,7 @@ namespace OpenSim.Framework
1802 startInfo.ThreadPoolName = "Util"; 1804 startInfo.ThreadPoolName = "Util";
1803 startInfo.IdleTimeout = 2000; 1805 startInfo.IdleTimeout = 2000;
1804 startInfo.MaxWorkerThreads = maxThreads; 1806 startInfo.MaxWorkerThreads = maxThreads;
1805 startInfo.MinWorkerThreads = 2; 1807 startInfo.MinWorkerThreads = minThreads;
1806 1808
1807 m_ThreadPool = new SmartThreadPool(startInfo); 1809 m_ThreadPool = new SmartThreadPool(startInfo);
1808 } 1810 }
@@ -1877,7 +1879,7 @@ namespace OpenSim.Framework
1877 break; 1879 break;
1878 case FireAndForgetMethod.SmartThreadPool: 1880 case FireAndForgetMethod.SmartThreadPool:
1879 if (m_ThreadPool == null) 1881 if (m_ThreadPool == null)
1880 InitThreadPool(15); 1882 InitThreadPool(2, 15);
1881 m_ThreadPool.QueueWorkItem((cb, o) => cb(o), realCallback, obj); 1883 m_ThreadPool.QueueWorkItem((cb, o) => cb(o), realCallback, obj);
1882 break; 1884 break;
1883 case FireAndForgetMethod.Thread: 1885 case FireAndForgetMethod.Thread:
@@ -2265,7 +2267,7 @@ namespace OpenSim.Framework
2265 { 2267 {
2266 lock (m_syncRoot) 2268 lock (m_syncRoot)
2267 { 2269 {
2268 m_lowQueue.Enqueue(data); 2270 q.Enqueue(data);
2269 m_s.WaitOne(0); 2271 m_s.WaitOne(0);
2270 m_s.Release(); 2272 m_s.Release();
2271 } 2273 }
@@ -2305,7 +2307,7 @@ namespace OpenSim.Framework
2305 { 2307 {
2306 if (m_highQueue.Count > 0) 2308 if (m_highQueue.Count > 0)
2307 res = m_highQueue.Dequeue(); 2309 res = m_highQueue.Dequeue();
2308 else 2310 else if (m_lowQueue.Count > 0)
2309 res = m_lowQueue.Dequeue(); 2311 res = m_lowQueue.Dequeue();
2310 2312
2311 if (m_highQueue.Count == 0 && m_lowQueue.Count == 0) 2313 if (m_highQueue.Count == 0 && m_lowQueue.Count == 0)
diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs
index 87c2792..6dd1f5b 100644
--- a/OpenSim/Region/Application/OpenSim.cs
+++ b/OpenSim/Region/Application/OpenSim.cs
@@ -86,6 +86,7 @@ namespace OpenSim
86 IConfig startupConfig = Config.Configs["Startup"]; 86 IConfig startupConfig = Config.Configs["Startup"];
87 IConfig networkConfig = Config.Configs["Network"]; 87 IConfig networkConfig = Config.Configs["Network"];
88 88
89 int stpMinThreads = 2;
89 int stpMaxThreads = 15; 90 int stpMaxThreads = 15;
90 91
91 if (startupConfig != null) 92 if (startupConfig != null)
@@ -112,12 +113,13 @@ namespace OpenSim
112 if (!String.IsNullOrEmpty(asyncCallMethodStr) && Utils.EnumTryParse<FireAndForgetMethod>(asyncCallMethodStr, out asyncCallMethod)) 113 if (!String.IsNullOrEmpty(asyncCallMethodStr) && Utils.EnumTryParse<FireAndForgetMethod>(asyncCallMethodStr, out asyncCallMethod))
113 Util.FireAndForgetMethod = asyncCallMethod; 114 Util.FireAndForgetMethod = asyncCallMethod;
114 115
116 stpMinThreads = startupConfig.GetInt("MinPoolThreads", 15);
115 stpMaxThreads = startupConfig.GetInt("MaxPoolThreads", 15); 117 stpMaxThreads = startupConfig.GetInt("MaxPoolThreads", 15);
116 m_consolePrompt = startupConfig.GetString("ConsolePrompt", @"Region (\R) "); 118 m_consolePrompt = startupConfig.GetString("ConsolePrompt", @"Region (\R) ");
117 } 119 }
118 120
119 if (Util.FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool) 121 if (Util.FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool)
120 Util.InitThreadPool(stpMaxThreads); 122 Util.InitThreadPool(stpMinThreads, stpMaxThreads);
121 123
122 m_log.Info("[OPENSIM MAIN]: Using async_call_method " + Util.FireAndForgetMethod); 124 m_log.Info("[OPENSIM MAIN]: Using async_call_method " + Util.FireAndForgetMethod);
123 } 125 }
@@ -423,8 +425,8 @@ namespace OpenSim
423 { 425 {
424 RegionInfo regionInfo = presence.Scene.RegionInfo; 426 RegionInfo regionInfo = presence.Scene.RegionInfo;
425 427
426 if (presence.Firstname.ToLower().Contains(mainParams[2].ToLower()) && 428 if (presence.Firstname.ToLower().Equals(mainParams[2].ToLower()) &&
427 presence.Lastname.ToLower().Contains(mainParams[3].ToLower())) 429 presence.Lastname.ToLower().Equals(mainParams[3].ToLower()))
428 { 430 {
429 MainConsole.Instance.Output( 431 MainConsole.Instance.Output(
430 String.Format( 432 String.Format(
@@ -438,6 +440,7 @@ namespace OpenSim
438 presence.ControllingClient.Kick("\nYou have been logged out by an administrator.\n"); 440 presence.ControllingClient.Kick("\nYou have been logged out by an administrator.\n");
439 441
440 presence.Scene.IncomingCloseAgent(presence.UUID, force); 442 presence.Scene.IncomingCloseAgent(presence.UUID, force);
443 break;
441 } 444 }
442 } 445 }
443 446
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
index 98ab433..762e22a 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
@@ -367,18 +367,7 @@ namespace OpenSim.Region.ClientStack.Linden
367 foreach (OSD c in capsRequested) 367 foreach (OSD c in capsRequested)
368 validCaps.Add(c.AsString()); 368 validCaps.Add(c.AsString());
369 369
370 Hashtable caps = m_HostCapsObj.CapsHandlers.GetCapsDetails(true, validCaps); 370 string result = LLSDHelpers.SerialiseLLSDReply(m_HostCapsObj.GetCapsDetails(true, validCaps));
371
372 // Add the external too
373 foreach (KeyValuePair<string, string> kvp in m_HostCapsObj.ExternalCapsHandlers)
374 {
375 if (!validCaps.Contains(kvp.Key))
376 continue;
377
378 caps[kvp.Key] = kvp.Value;
379 }
380
381 string result = LLSDHelpers.SerialiseLLSDReply(caps);
382 371
383 //m_log.DebugFormat("[CAPS] CapsRequest {0}", result); 372 //m_log.DebugFormat("[CAPS] CapsRequest {0}", result);
384 373
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
index d6689d4..e98a470 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
@@ -65,6 +65,13 @@ namespace OpenSim.Region.ClientStack.Linden
65 /// </value> 65 /// </value>
66 public int DebugLevel { get; set; } 66 public int DebugLevel { get; set; }
67 67
68 // Viewer post requests timeout in 60 secs
69 // https://bitbucket.org/lindenlab/viewer-release/src/421c20423df93d650cc305dc115922bb30040999/indra/llmessage/llhttpclient.cpp?at=default#cl-44
70 //
71 private const int VIEWER_TIMEOUT = 60 * 1000;
72 // Just to be safe, we work on a 10 sec shorter cycle
73 private const int SERVER_EQ_TIME_NO_EVENTS = VIEWER_TIMEOUT - (10 * 1000);
74
68 protected Scene m_scene; 75 protected Scene m_scene;
69 76
70 private Dictionary<UUID, int> m_ids = new Dictionary<UUID, int>(); 77 private Dictionary<UUID, int> m_ids = new Dictionary<UUID, int>();
@@ -252,29 +259,32 @@ namespace OpenSim.Region.ClientStack.Linden
252 259
253 List<UUID> removeitems = new List<UUID>(); 260 List<UUID> removeitems = new List<UUID>();
254 lock (m_AvatarQueueUUIDMapping) 261 lock (m_AvatarQueueUUIDMapping)
255 { 262 m_AvatarQueueUUIDMapping.Remove(agentID);
256 foreach (UUID ky in m_AvatarQueueUUIDMapping.Keys)
257 {
258// m_log.DebugFormat("[EVENTQUEUE]: Found key {0} in m_AvatarQueueUUIDMapping while looking for {1}", ky, AgentID);
259 if (ky == agentID)
260 {
261 removeitems.Add(ky);
262 }
263 }
264 263
265 foreach (UUID ky in removeitems) 264// lock (m_AvatarQueueUUIDMapping)
266 { 265// {
267 UUID eventQueueGetUuid = m_AvatarQueueUUIDMapping[ky]; 266// foreach (UUID ky in m_AvatarQueueUUIDMapping.Keys)
268 m_AvatarQueueUUIDMapping.Remove(ky); 267// {
269 268//// m_log.DebugFormat("[EVENTQUEUE]: Found key {0} in m_AvatarQueueUUIDMapping while looking for {1}", ky, AgentID);
270 string eqgPath = GenerateEqgCapPath(eventQueueGetUuid); 269// if (ky == agentID)
271 MainServer.Instance.RemovePollServiceHTTPHandler("", eqgPath); 270// {
272 271// removeitems.Add(ky);
273// m_log.DebugFormat( 272// }
274// "[EVENT QUEUE GET MODULE]: Removed EQG handler {0} for {1} in {2}", 273// }
275// eqgPath, agentID, m_scene.RegionInfo.RegionName); 274//
276 } 275// foreach (UUID ky in removeitems)
277 } 276// {
277// UUID eventQueueGetUuid = m_AvatarQueueUUIDMapping[ky];
278// m_AvatarQueueUUIDMapping.Remove(ky);
279//
280// string eqgPath = GenerateEqgCapPath(eventQueueGetUuid);
281// MainServer.Instance.RemovePollServiceHTTPHandler("", eqgPath);
282//
283//// m_log.DebugFormat(
284//// "[EVENT QUEUE GET MODULE]: Removed EQG handler {0} for {1} in {2}",
285//// eqgPath, agentID, m_scene.RegionInfo.RegionName);
286// }
287// }
278 288
279 UUID searchval = UUID.Zero; 289 UUID searchval = UUID.Zero;
280 290
@@ -359,29 +369,9 @@ namespace OpenSim.Region.ClientStack.Linden
359 m_AvatarQueueUUIDMapping.Add(agentID, eventQueueGetUUID); 369 m_AvatarQueueUUIDMapping.Add(agentID, eventQueueGetUUID);
360 } 370 }
361 371
362 string eventQueueGetPath = GenerateEqgCapPath(eventQueueGetUUID); 372 caps.RegisterPollHandler(
363 373 "EventQueueGet",
364 // Register this as a caps handler 374 new PollServiceEventArgs(null, GenerateEqgCapPath(eventQueueGetUUID), HasEvents, GetEvents, NoEvents, agentID, SERVER_EQ_TIME_NO_EVENTS));
365 // FIXME: Confusingly, we need to register separate as a capability so that the client is told about
366 // EventQueueGet when it receive capability information, but then we replace the rest handler immediately
367 // afterwards with the poll service. So for now, we'll pass a null instead to simplify code reading, but
368 // really it should be possible to directly register the poll handler as a capability.
369 caps.RegisterHandler(
370 "EventQueueGet", new RestHTTPHandler("POST", eventQueueGetPath, null, "EventQueueGet", null));
371// delegate(Hashtable m_dhttpMethod)
372// {
373// return ProcessQueue(m_dhttpMethod, agentID, caps);
374// }));
375
376 // This will persist this beyond the expiry of the caps handlers
377 // TODO: Add EventQueueGet name/description for diagnostics
378 MainServer.Instance.AddPollServiceHTTPHandler(
379 eventQueueGetPath,
380 new PollServiceEventArgs(null, HasEvents, GetEvents, NoEvents, agentID, 40000));
381
382// m_log.DebugFormat(
383// "[EVENT QUEUE GET MODULE]: Registered EQG handler {0} for {1} in {2}",
384// eventQueueGetPath, agentID, m_scene.RegionInfo.RegionName);
385 375
386 Random rnd = new Random(Environment.TickCount); 376 Random rnd = new Random(Environment.TickCount);
387 lock (m_ids) 377 lock (m_ids)
@@ -399,7 +389,10 @@ namespace OpenSim.Region.ClientStack.Linden
399 Queue<OSD> queue = GetQueue(agentID); 389 Queue<OSD> queue = GetQueue(agentID);
400 if (queue != null) 390 if (queue != null)
401 lock (queue) 391 lock (queue)
392 {
393 //m_log.WarnFormat("POLLED FOR EVENTS BY {0} in {1} -- {2}", agentID, m_scene.RegionInfo.RegionName, queue.Count);
402 return queue.Count > 0; 394 return queue.Count > 0;
395 }
403 396
404 return false; 397 return false;
405 } 398 }
@@ -422,7 +415,7 @@ namespace OpenSim.Region.ClientStack.Linden
422 public Hashtable GetEvents(UUID requestID, UUID pAgentId) 415 public Hashtable GetEvents(UUID requestID, UUID pAgentId)
423 { 416 {
424 if (DebugLevel >= 2) 417 if (DebugLevel >= 2)
425 m_log.DebugFormat("POLLED FOR EQ MESSAGES BY {0} in {1}", pAgentId, m_scene.RegionInfo.RegionName); 418 m_log.WarnFormat("POLLED FOR EQ MESSAGES BY {0} in {1}", pAgentId, m_scene.RegionInfo.RegionName);
426 419
427 Queue<OSD> queue = TryGetQueue(pAgentId); 420 Queue<OSD> queue = TryGetQueue(pAgentId);
428 OSD element; 421 OSD element;
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs
index 6ec1115..7b15284 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs
@@ -246,8 +246,8 @@ namespace OpenSim.Region.ClientStack.Linden
246 246
247 private Scene m_scene; 247 private Scene m_scene;
248 private MeshCapsDataThrottler m_throttler; 248 private MeshCapsDataThrottler m_throttler;
249 public PollServiceMeshEventArgs(UUID pId, Scene scene) : 249 public PollServiceMeshEventArgs(string uri, UUID pId, Scene scene) :
250 base(null, null, null, null, pId, int.MaxValue) 250 base(null, uri, null, null, null, pId, int.MaxValue)
251 { 251 {
252 m_scene = scene; 252 m_scene = scene;
253 m_throttler = new MeshCapsDataThrottler(100000, 1400000, 10000, scene, pId); 253 m_throttler = new MeshCapsDataThrottler(100000, 1400000, 10000, scene, pId);
@@ -361,7 +361,7 @@ namespace OpenSim.Region.ClientStack.Linden
361 string capUrl = "/CAPS/" + UUID.Random() + "/"; 361 string capUrl = "/CAPS/" + UUID.Random() + "/";
362 362
363 // Register this as a poll service 363 // Register this as a poll service
364 PollServiceMeshEventArgs args = new PollServiceMeshEventArgs(agentID, m_scene); 364 PollServiceMeshEventArgs args = new PollServiceMeshEventArgs(capUrl, agentID, m_scene);
365 365
366 args.Type = PollServiceEventArgs.EventType.Mesh; 366 args.Type = PollServiceEventArgs.EventType.Mesh;
367 MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args); 367 MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args);
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs
index a42c96c..c12b8d6 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs
@@ -210,7 +210,7 @@ namespace OpenSim.Region.ClientStack.Linden
210 private Scene m_scene; 210 private Scene m_scene;
211 private CapsDataThrottler m_throttler = new CapsDataThrottler(100000, 1400000,10000); 211 private CapsDataThrottler m_throttler = new CapsDataThrottler(100000, 1400000,10000);
212 public PollServiceTextureEventArgs(UUID pId, Scene scene) : 212 public PollServiceTextureEventArgs(UUID pId, Scene scene) :
213 base(null, null, null, null, pId, int.MaxValue) 213 base(null, "", null, null, null, pId, int.MaxValue)
214 { 214 {
215 m_scene = scene; 215 m_scene = scene;
216 // x is request id, y is userid 216 // x is request id, y is userid
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
index 27b09a6..f816ad3 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
@@ -78,7 +78,6 @@ namespace OpenSim.Region.ClientStack.Linden
78 78
79 private static WebFetchInvDescHandler m_webFetchHandler; 79 private static WebFetchInvDescHandler m_webFetchHandler;
80 80
81 private Dictionary<UUID, string> m_capsDict = new Dictionary<UUID, string>();
82 private static Thread[] m_workerThreads = null; 81 private static Thread[] m_workerThreads = null;
83 82
84 private static DoubleQueue<aPollRequest> m_queue = 83 private static DoubleQueue<aPollRequest> m_queue =
@@ -115,7 +114,6 @@ namespace OpenSim.Region.ClientStack.Linden
115 return; 114 return;
116 115
117 m_scene.EventManager.OnRegisterCaps -= RegisterCaps; 116 m_scene.EventManager.OnRegisterCaps -= RegisterCaps;
118 m_scene.EventManager.OnDeregisterCaps -= DeregisterCaps;
119 117
120 foreach (Thread t in m_workerThreads) 118 foreach (Thread t in m_workerThreads)
121 Watchdog.AbortThread(t.ManagedThreadId); 119 Watchdog.AbortThread(t.ManagedThreadId);
@@ -135,7 +133,6 @@ namespace OpenSim.Region.ClientStack.Linden
135 m_webFetchHandler = new WebFetchInvDescHandler(m_InventoryService, m_LibraryService); 133 m_webFetchHandler = new WebFetchInvDescHandler(m_InventoryService, m_LibraryService);
136 134
137 m_scene.EventManager.OnRegisterCaps += RegisterCaps; 135 m_scene.EventManager.OnRegisterCaps += RegisterCaps;
138 m_scene.EventManager.OnDeregisterCaps += DeregisterCaps;
139 136
140 if (m_workerThreads == null) 137 if (m_workerThreads == null)
141 { 138 {
@@ -178,8 +175,8 @@ namespace OpenSim.Region.ClientStack.Linden
178 175
179 private Scene m_scene; 176 private Scene m_scene;
180 177
181 public PollServiceInventoryEventArgs(Scene scene, UUID pId) : 178 public PollServiceInventoryEventArgs(Scene scene, string url, UUID pId) :
182 base(null, null, null, null, pId, int.MaxValue) 179 base(null, url, null, null, null, pId, int.MaxValue)
183 { 180 {
184 m_scene = scene; 181 m_scene = scene;
185 182
@@ -310,40 +307,39 @@ namespace OpenSim.Region.ClientStack.Linden
310 if (m_fetchInventoryDescendents2Url == "") 307 if (m_fetchInventoryDescendents2Url == "")
311 return; 308 return;
312 309
313 string capUrl = "/CAPS/" + UUID.Random() + "/";
314
315 // Register this as a poll service 310 // Register this as a poll service
316 PollServiceInventoryEventArgs args = new PollServiceInventoryEventArgs(m_scene, agentID); 311 PollServiceInventoryEventArgs args
317 312 = new PollServiceInventoryEventArgs(m_scene, "/CAPS/" + UUID.Random() + "/", agentID);
318 args.Type = PollServiceEventArgs.EventType.Inventory; 313 args.Type = PollServiceEventArgs.EventType.Inventory;
319 MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args);
320
321 string hostName = m_scene.RegionInfo.ExternalHostName;
322 uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port;
323 string protocol = "http";
324
325 if (MainServer.Instance.UseSSL)
326 {
327 hostName = MainServer.Instance.SSLCommonName;
328 port = MainServer.Instance.SSLPort;
329 protocol = "https";
330 }
331
332 caps.RegisterHandler("FetchInventoryDescendents2", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl));
333 314
334 m_capsDict[agentID] = capUrl; 315 caps.RegisterPollHandler("FetchInventoryDescendents2", args);
316
317// MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args);
318//
319// string hostName = m_scene.RegionInfo.ExternalHostName;
320// uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port;
321// string protocol = "http";
322//
323// if (MainServer.Instance.UseSSL)
324// {
325// hostName = MainServer.Instance.SSLCommonName;
326// port = MainServer.Instance.SSLPort;
327// protocol = "https";
328// }
329//
330// caps.RegisterHandler("FetchInventoryDescendents2", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl));
335 } 331 }
336 332
337 private void DeregisterCaps(UUID agentID, Caps caps) 333// private void DeregisterCaps(UUID agentID, Caps caps)
338 { 334// {
339 string capUrl; 335// string capUrl;
340 336//
341 if (m_capsDict.TryGetValue(agentID, out capUrl)) 337// if (m_capsDict.TryGetValue(agentID, out capUrl))
342 { 338// {
343 MainServer.Instance.RemoveHTTPHandler("", capUrl); 339// MainServer.Instance.RemoveHTTPHandler("", capUrl);
344 m_capsDict.Remove(agentID); 340// m_capsDict.Remove(agentID);
345 } 341// }
346 } 342// }
347 343
348 private void DoInventoryRequests() 344 private void DoInventoryRequests()
349 { 345 {
@@ -353,7 +349,8 @@ namespace OpenSim.Region.ClientStack.Linden
353 349
354 aPollRequest poolreq = m_queue.Dequeue(); 350 aPollRequest poolreq = m_queue.Dequeue();
355 351
356 poolreq.thepoll.Process(poolreq); 352 if (poolreq != null && poolreq.thepoll != null)
353 poolreq.thepoll.Process(poolreq);
357 } 354 }
358 } 355 }
359 } 356 }
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index dfad485..ac5e77e 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -3816,6 +3816,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3816 ResendPrimUpdate(update); 3816 ResendPrimUpdate(update);
3817 } 3817 }
3818 3818
3819// OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>();
3820// OpenSim.Framework.Lazy<List<ObjectUpdateCompressedPacket.ObjectDataBlock>> compressedUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdateCompressedPacket.ObjectDataBlock>>();
3821// OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>();
3822// OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseAgentUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>();
3823//
3824// OpenSim.Framework.Lazy<List<EntityUpdate>> objectUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3825// OpenSim.Framework.Lazy<List<EntityUpdate>> compressedUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3826// OpenSim.Framework.Lazy<List<EntityUpdate>> terseUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3827// OpenSim.Framework.Lazy<List<EntityUpdate>> terseAgentUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3828
3829
3819 private void ProcessEntityUpdates(int maxUpdates) 3830 private void ProcessEntityUpdates(int maxUpdates)
3820 { 3831 {
3821 OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>(); 3832 OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>();
@@ -3828,6 +3839,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3828 OpenSim.Framework.Lazy<List<EntityUpdate>> terseUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>(); 3839 OpenSim.Framework.Lazy<List<EntityUpdate>> terseUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3829 OpenSim.Framework.Lazy<List<EntityUpdate>> terseAgentUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>(); 3840 OpenSim.Framework.Lazy<List<EntityUpdate>> terseAgentUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3830 3841
3842// objectUpdateBlocks.Value.Clear();
3843// compressedUpdateBlocks.Value.Clear();
3844// terseUpdateBlocks.Value.Clear();
3845// terseAgentUpdateBlocks.Value.Clear();
3846// objectUpdates.Value.Clear();
3847// compressedUpdates.Value.Clear();
3848// terseUpdates.Value.Clear();
3849// terseAgentUpdates.Value.Clear();
3850
3831 // Check to see if this is a flush 3851 // Check to see if this is a flush
3832 if (maxUpdates <= 0) 3852 if (maxUpdates <= 0)
3833 { 3853 {
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
index 77b07ed..b4ac021 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
@@ -809,8 +809,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
809 } 809 }
810 810
811 PacketPool.Instance.ReturnPacket(packet); 811 PacketPool.Instance.ReturnPacket(packet);
812 m_dataPresentEvent.Set();
813
812 } 814 }
813 815
816 private AutoResetEvent m_dataPresentEvent = new AutoResetEvent(false);
817
814 /// <summary> 818 /// <summary>
815 /// Start the process of sending a packet to the client. 819 /// Start the process of sending a packet to the client.
816 /// </summary> 820 /// </summary>
@@ -1730,6 +1734,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1730 // Action generic every round 1734 // Action generic every round
1731 Action<IClientAPI> clientPacketHandler = ClientOutgoingPacketHandler; 1735 Action<IClientAPI> clientPacketHandler = ClientOutgoingPacketHandler;
1732 1736
1737// while (true)
1733 while (base.IsRunningOutbound) 1738 while (base.IsRunningOutbound)
1734 { 1739 {
1735 m_scene.ThreadAlive(2); 1740 m_scene.ThreadAlive(2);
@@ -1791,8 +1796,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1791 1796
1792 // If nothing was sent, sleep for the minimum amount of time before a 1797 // If nothing was sent, sleep for the minimum amount of time before a
1793 // token bucket could get more tokens 1798 // token bucket could get more tokens
1794 if (!m_packetSent) 1799 //if (!m_packetSent)
1795 Thread.Sleep((int)TickCountResolution); 1800 // Thread.Sleep((int)TickCountResolution);
1801 m_dataPresentEvent.WaitOne(100);
1796 1802
1797 Watchdog.UpdateThread(); 1803 Watchdog.UpdateThread();
1798 } 1804 }
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index a60b314..505bb53 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
@@ -75,10 +75,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
75 public void AddRegion(Scene scene) 75 public void AddRegion(Scene scene)
76 { 76 {
77 m_scene = scene; 77 m_scene = scene;
78 m_scene.RegisterModuleInterface<IAttachmentsModule>(this);
79
80 if (Enabled) 78 if (Enabled)
81 { 79 {
80 // Only register module with scene if it is enabled. All callers check for a null attachments module.
81 // Ideally, there should be a null attachments module for when this core attachments module has been
82 // disabled. Registering only when enabled allows for other attachments module implementations.
83 m_scene.RegisterModuleInterface<IAttachmentsModule>(this);
82 m_scene.EventManager.OnNewClient += SubscribeToClientEvents; 84 m_scene.EventManager.OnNewClient += SubscribeToClientEvents;
83 m_scene.EventManager.OnStartScript += (localID, itemID) => HandleScriptStateChange(localID, true); 85 m_scene.EventManager.OnStartScript += (localID, itemID) => HandleScriptStateChange(localID, true);
84 m_scene.EventManager.OnStopScript += (localID, itemID) => HandleScriptStateChange(localID, false); 86 m_scene.EventManager.OnStopScript += (localID, itemID) => HandleScriptStateChange(localID, false);
diff --git a/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs b/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs
index 6ce6227..0c759df 100644
--- a/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs
@@ -80,7 +80,7 @@ namespace OpenSim.Region.CoreModules.Framework
80 80
81 MainConsole.Instance.Commands.AddCommand( 81 MainConsole.Instance.Commands.AddCommand(
82 "Comms", false, "show caps stats by user", 82 "Comms", false, "show caps stats by user",
83 "show caps stats [<first-name> <last-name>]", 83 "show caps stats by user [<first-name> <last-name>]",
84 "Shows statistics on capabilities use by user.", 84 "Shows statistics on capabilities use by user.",
85 "If a user name is given, then prints a detailed breakdown of caps use ordered by number of requests received.", 85 "If a user name is given, then prints a detailed breakdown of caps use ordered by number of requests received.",
86 HandleShowCapsStatsByUserCommand); 86 HandleShowCapsStatsByUserCommand);
@@ -296,27 +296,31 @@ namespace OpenSim.Region.CoreModules.Framework
296 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene) 296 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene)
297 return; 297 return;
298 298
299 StringBuilder caps = new StringBuilder(); 299 StringBuilder capsReport = new StringBuilder();
300 caps.AppendFormat("Region {0}:\n", m_scene.RegionInfo.RegionName); 300 capsReport.AppendFormat("Region {0}:\n", m_scene.RegionInfo.RegionName);
301 301
302 lock (m_capsObjects) 302 lock (m_capsObjects)
303 { 303 {
304 foreach (KeyValuePair<uint, Caps> kvp in m_capsObjects) 304 foreach (KeyValuePair<uint, Caps> kvp in m_capsObjects)
305 { 305 {
306 caps.AppendFormat("** Circuit {0}:\n", kvp.Key); 306 capsReport.AppendFormat("** Circuit {0}:\n", kvp.Key);
307 Caps caps = kvp.Value;
307 308
308 for (IDictionaryEnumerator kvp2 = kvp.Value.CapsHandlers.GetCapsDetails(false, null).GetEnumerator(); kvp2.MoveNext(); ) 309 for (IDictionaryEnumerator kvp2 = caps.CapsHandlers.GetCapsDetails(false, null).GetEnumerator(); kvp2.MoveNext(); )
309 { 310 {
310 Uri uri = new Uri(kvp2.Value.ToString()); 311 Uri uri = new Uri(kvp2.Value.ToString());
311 caps.AppendFormat(m_showCapsCommandFormat, kvp2.Key, uri.PathAndQuery); 312 capsReport.AppendFormat(m_showCapsCommandFormat, kvp2.Key, uri.PathAndQuery);
312 } 313 }
313 314
314 foreach (KeyValuePair<string, string> kvp3 in kvp.Value.ExternalCapsHandlers) 315 foreach (KeyValuePair<string, PollServiceEventArgs> kvp2 in caps.GetPollHandlers())
315 caps.AppendFormat(m_showCapsCommandFormat, kvp3.Key, kvp3.Value); 316 capsReport.AppendFormat(m_showCapsCommandFormat, kvp2.Key, kvp2.Value.Url);
317
318 foreach (KeyValuePair<string, string> kvp3 in caps.ExternalCapsHandlers)
319 capsReport.AppendFormat(m_showCapsCommandFormat, kvp3.Key, kvp3.Value);
316 } 320 }
317 } 321 }
318 322
319 MainConsole.Instance.Output(caps.ToString()); 323 MainConsole.Instance.Output(capsReport.ToString());
320 } 324 }
321 325
322 private void HandleShowCapsStatsByCapCommand(string module, string[] cmdParams) 326 private void HandleShowCapsStatsByCapCommand(string module, string[] cmdParams)
@@ -374,7 +378,16 @@ namespace OpenSim.Region.CoreModules.Framework
374 { 378 {
375 receivedStats[sp.Name] = reqHandler.RequestsReceived; 379 receivedStats[sp.Name] = reqHandler.RequestsReceived;
376 handledStats[sp.Name] = reqHandler.RequestsHandled; 380 handledStats[sp.Name] = reqHandler.RequestsHandled;
377 } 381 }
382 else
383 {
384 PollServiceEventArgs pollHandler = null;
385 if (caps.TryGetPollHandler(capName, out pollHandler))
386 {
387 receivedStats[sp.Name] = pollHandler.RequestsReceived;
388 handledStats[sp.Name] = pollHandler.RequestsHandled;
389 }
390 }
378 } 391 }
379 ); 392 );
380 393
@@ -405,11 +418,9 @@ namespace OpenSim.Region.CoreModules.Framework
405 Caps caps = m_scene.CapsModule.GetCapsForUser(sp.UUID); 418 Caps caps = m_scene.CapsModule.GetCapsForUser(sp.UUID);
406 419
407 if (caps == null) 420 if (caps == null)
408 return; 421 return;
409
410 Dictionary<string, IRequestHandler> capsHandlers = caps.CapsHandlers.GetCapsHandlers();
411 422
412 foreach (IRequestHandler reqHandler in capsHandlers.Values) 423 foreach (IRequestHandler reqHandler in caps.CapsHandlers.GetCapsHandlers().Values)
413 { 424 {
414 string reqName = reqHandler.Name ?? ""; 425 string reqName = reqHandler.Name ?? "";
415 426
@@ -424,6 +435,23 @@ namespace OpenSim.Region.CoreModules.Framework
424 handledStats[reqName] += reqHandler.RequestsHandled; 435 handledStats[reqName] += reqHandler.RequestsHandled;
425 } 436 }
426 } 437 }
438
439 foreach (KeyValuePair<string, PollServiceEventArgs> kvp in caps.GetPollHandlers())
440 {
441 string name = kvp.Key;
442 PollServiceEventArgs pollHandler = kvp.Value;
443
444 if (!receivedStats.ContainsKey(name))
445 {
446 receivedStats[name] = pollHandler.RequestsReceived;
447 handledStats[name] = pollHandler.RequestsHandled;
448 }
449 else
450 {
451 receivedStats[name] += pollHandler.RequestsReceived;
452 handledStats[name] += pollHandler.RequestsHandled;
453 }
454 }
427 } 455 }
428 ); 456 );
429 457
@@ -486,12 +514,16 @@ namespace OpenSim.Region.CoreModules.Framework
486 if (caps == null) 514 if (caps == null)
487 return; 515 return;
488 516
489 Dictionary<string, IRequestHandler> capsHandlers = caps.CapsHandlers.GetCapsHandlers(); 517 List<CapTableRow> capRows = new List<CapTableRow>();
490 518
491 foreach (IRequestHandler reqHandler in capsHandlers.Values.OrderByDescending(rh => rh.RequestsReceived)) 519 foreach (IRequestHandler reqHandler in caps.CapsHandlers.GetCapsHandlers().Values)
492 { 520 capRows.Add(new CapTableRow(reqHandler.Name, reqHandler.RequestsReceived, reqHandler.RequestsHandled));
493 cdt.AddRow(reqHandler.Name, reqHandler.RequestsReceived, reqHandler.RequestsHandled); 521
494 } 522 foreach (KeyValuePair<string, PollServiceEventArgs> kvp in caps.GetPollHandlers())
523 capRows.Add(new CapTableRow(kvp.Key, kvp.Value.RequestsReceived, kvp.Value.RequestsHandled));
524
525 foreach (CapTableRow ctr in capRows.OrderByDescending(ctr => ctr.RequestsReceived))
526 cdt.AddRow(ctr.Name, ctr.RequestsReceived, ctr.RequestsHandled);
495 527
496 sb.Append(cdt.ToString()); 528 sb.Append(cdt.ToString());
497 */ 529 */
@@ -525,6 +557,14 @@ namespace OpenSim.Region.CoreModules.Framework
525 totalRequestsReceived += reqHandler.RequestsReceived; 557 totalRequestsReceived += reqHandler.RequestsReceived;
526 totalRequestsHandled += reqHandler.RequestsHandled; 558 totalRequestsHandled += reqHandler.RequestsHandled;
527 } 559 }
560
561 Dictionary<string, PollServiceEventArgs> capsPollHandlers = caps.GetPollHandlers();
562
563 foreach (PollServiceEventArgs handler in capsPollHandlers.Values)
564 {
565 totalRequestsReceived += handler.RequestsReceived;
566 totalRequestsHandled += handler.RequestsHandled;
567 }
528 568
529 cdt.AddRow(sp.Name, sp.IsChildAgent ? "child" : "root", totalRequestsReceived, totalRequestsHandled); 569 cdt.AddRow(sp.Name, sp.IsChildAgent ? "child" : "root", totalRequestsReceived, totalRequestsHandled);
530 } 570 }
@@ -533,5 +573,19 @@ namespace OpenSim.Region.CoreModules.Framework
533 sb.Append(cdt.ToString()); 573 sb.Append(cdt.ToString());
534 */ 574 */
535 } 575 }
576
577 private class CapTableRow
578 {
579 public string Name { get; set; }
580 public int RequestsReceived { get; set; }
581 public int RequestsHandled { get; set; }
582
583 public CapTableRow(string name, int requestsReceived, int requestsHandled)
584 {
585 Name = name;
586 RequestsReceived = requestsReceived;
587 RequestsHandled = requestsHandled;
588 }
589 }
536 } 590 }
537} 591}
diff --git a/OpenSim/Region/CoreModules/Framework/GridServiceThrottle/GridServiceThrottleModule.cs b/OpenSim/Region/CoreModules/Framework/ServiceThrottle/ServiceThrottleModule.cs
index f1eb1ad..a70261e 100644
--- a/OpenSim/Region/CoreModules/Framework/GridServiceThrottle/GridServiceThrottleModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/ServiceThrottle/ServiceThrottleModule.cs
@@ -42,23 +42,37 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion;
42namespace OpenSim.Region.CoreModules.Framework 42namespace OpenSim.Region.CoreModules.Framework
43{ 43{
44 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GridServiceThrottleModule")] 44 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GridServiceThrottleModule")]
45 public class GridServiceThrottleModule : ISharedRegionModule 45 public class ServiceThrottleModule : ISharedRegionModule, IServiceThrottleModule
46 { 46 {
47 private static readonly ILog m_log = LogManager.GetLogger( 47 private static readonly ILog m_log = LogManager.GetLogger(
48 MethodBase.GetCurrentMethod().DeclaringType); 48 MethodBase.GetCurrentMethod().DeclaringType);
49 49
50 private readonly List<Scene> m_scenes = new List<Scene>(); 50 private readonly List<Scene> m_scenes = new List<Scene>();
51 private System.Timers.Timer m_timer = new System.Timers.Timer();
51 52
52 private OpenSim.Framework.BlockingQueue<GridRegionRequest> m_RequestQueue = new OpenSim.Framework.BlockingQueue<GridRegionRequest>(); 53 private Queue<Action> m_RequestQueue = new Queue<Action>();
54 private Dictionary<string, List<string>> m_Pending = new Dictionary<string, List<string>>();
55 private int m_Interval;
56
57 #region ISharedRegionModule
53 58
54 public void Initialise(IConfigSource config) 59 public void Initialise(IConfigSource config)
55 { 60 {
56 Watchdog.StartThread( 61 m_Interval = Util.GetConfigVarFromSections<int>(config, "Interval", new string[] { "ServiceThrottle" }, 5000);
57 ProcessQueue, 62
58 "GridServiceRequestThread", 63 m_timer = new System.Timers.Timer();
59 ThreadPriority.BelowNormal, 64 m_timer.AutoReset = false;
60 true, 65 m_timer.Enabled = true;
61 false); 66 m_timer.Interval = 15000; // 15 secs at first
67 m_timer.Elapsed += ProcessQueue;
68 m_timer.Start();
69
70 //Watchdog.StartThread(
71 // ProcessQueue,
72 // "GridServiceRequestThread",
73 // ThreadPriority.BelowNormal,
74 // true,
75 // false);
62 } 76 }
63 77
64 public void AddRegion(Scene scene) 78 public void AddRegion(Scene scene)
@@ -66,7 +80,9 @@ namespace OpenSim.Region.CoreModules.Framework
66 lock (m_scenes) 80 lock (m_scenes)
67 { 81 {
68 m_scenes.Add(scene); 82 m_scenes.Add(scene);
83 scene.RegisterModuleInterface<IServiceThrottleModule>(this);
69 scene.EventManager.OnNewClient += OnNewClient; 84 scene.EventManager.OnNewClient += OnNewClient;
85 scene.EventManager.OnMakeRootAgent += OnMakeRootAgent;
70 } 86 }
71 } 87 }
72 88
@@ -83,11 +99,6 @@ namespace OpenSim.Region.CoreModules.Framework
83 } 99 }
84 } 100 }
85 101
86 void OnNewClient(IClientAPI client)
87 {
88 client.OnRegionHandleRequest += OnRegionHandleRequest;
89 }
90
91 public void PostInitialise() 102 public void PostInitialise()
92 { 103 {
93 } 104 }
@@ -98,7 +109,7 @@ namespace OpenSim.Region.CoreModules.Framework
98 109
99 public string Name 110 public string Name
100 { 111 {
101 get { return "GridServiceThrottleModule"; } 112 get { return "ServiceThrottleModule"; }
102 } 113 }
103 114
104 public Type ReplaceableInterface 115 public Type ReplaceableInterface
@@ -106,9 +117,31 @@ namespace OpenSim.Region.CoreModules.Framework
106 get { return null; } 117 get { return null; }
107 } 118 }
108 119
120 #endregion ISharedRegionMOdule
121
122 #region Events
123
124 void OnNewClient(IClientAPI client)
125 {
126 client.OnRegionHandleRequest += OnRegionHandleRequest;
127 }
128
129 void OnMakeRootAgent(ScenePresence obj)
130 {
131 lock (m_timer)
132 {
133 if (!m_timer.Enabled)
134 {
135 m_timer.Interval = m_Interval;
136 m_timer.Enabled = true;
137 m_timer.Start();
138 }
139 }
140 }
141
109 public void OnRegionHandleRequest(IClientAPI client, UUID regionID) 142 public void OnRegionHandleRequest(IClientAPI client, UUID regionID)
110 { 143 {
111 //m_log.DebugFormat("[GRIDSERVICE THROTTLE]: RegionHandleRequest {0}", regionID); 144 //m_log.DebugFormat("[SERVICE THROTTLE]: RegionHandleRequest {0}", regionID);
112 ulong handle = 0; 145 ulong handle = 0;
113 if (IsLocalRegionHandle(regionID, out handle)) 146 if (IsLocalRegionHandle(regionID, out handle))
114 { 147 {
@@ -116,11 +149,83 @@ namespace OpenSim.Region.CoreModules.Framework
116 return; 149 return;
117 } 150 }
118 151
119 GridRegionRequest request = new GridRegionRequest(client, regionID); 152 Action action = delegate
120 m_RequestQueue.Enqueue(request); 153 {
154 GridRegion r = m_scenes[0].GridService.GetRegionByUUID(UUID.Zero, regionID);
155
156 if (r != null && r.RegionHandle != 0)
157 client.SendRegionHandle(regionID, r.RegionHandle);
158 };
159
160 Enqueue("region", regionID.ToString(), action);
161 }
162
163 #endregion Events
164
165 #region IServiceThrottleModule
166
167 public void Enqueue(string category, string itemid, Action continuation)
168 {
169 lock (m_RequestQueue)
170 {
171 if (m_Pending.ContainsKey(category))
172 {
173 if (m_Pending[category].Contains(itemid))
174 // Don't enqueue, it's already pending
175 return;
176 }
177 else
178 m_Pending.Add(category, new List<string>());
179
180 m_Pending[category].Add(itemid);
181
182 m_RequestQueue.Enqueue(delegate
183 {
184 lock (m_RequestQueue)
185 m_Pending[category].Remove(itemid);
186
187 continuation();
188 });
189 }
190 }
191
192 #endregion IServiceThrottleModule
193
194 #region Process Continuation Queue
195
196 private void ProcessQueue(object sender, System.Timers.ElapsedEventArgs e)
197 {
198 //m_log.DebugFormat("[YYY]: Process queue with {0} continuations", m_RequestQueue.Count);
199
200 while (m_RequestQueue.Count > 0)
201 {
202 Action continuation = null;
203 lock (m_RequestQueue)
204 continuation = m_RequestQueue.Dequeue();
205
206 if (continuation != null)
207 continuation();
208 }
209
210 if (AreThereRootAgents())
211 {
212 lock (m_timer)
213 {
214 m_timer.Interval = 1000; // 1 sec
215 m_timer.Enabled = true;
216 m_timer.Start();
217 }
218 }
219 else
220 lock (m_timer)
221 m_timer.Enabled = false;
121 222
122 } 223 }
123 224
225 #endregion Process Continuation Queue
226
227 #region Misc
228
124 private bool IsLocalRegionHandle(UUID regionID, out ulong regionHandle) 229 private bool IsLocalRegionHandle(UUID regionID, out ulong regionHandle)
125 { 230 {
126 regionHandle = 0; 231 regionHandle = 0;
@@ -133,31 +238,19 @@ namespace OpenSim.Region.CoreModules.Framework
133 return false; 238 return false;
134 } 239 }
135 240
136 private void ProcessQueue() 241 private bool AreThereRootAgents()
137 { 242 {
138 while (true) 243 foreach (Scene s in m_scenes)
139 { 244 {
140 Watchdog.UpdateThread(); 245 foreach (ScenePresence sp in s.GetScenePresences())
141 246 if (!sp.IsChildAgent)
142 GridRegionRequest request = m_RequestQueue.Dequeue(); 247 return true;
143 GridRegion r = m_scenes[0].GridService.GetRegionByUUID(UUID.Zero, request.regionID);
144
145 if (r != null && r.RegionHandle != 0)
146 request.client.SendRegionHandle(request.regionID, r.RegionHandle);
147
148 } 248 }
149 }
150 }
151
152 class GridRegionRequest
153 {
154 public IClientAPI client;
155 public UUID regionID;
156 249
157 public GridRegionRequest(IClientAPI c, UUID r) 250 return false;
158 {
159 client = c;
160 regionID = r;
161 } 251 }
252
253 #endregion Misc
162 } 254 }
255
163} 256}
diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
index a528093..a91adfa 100644
--- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
@@ -56,13 +56,10 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
56 protected bool m_Enabled; 56 protected bool m_Enabled;
57 protected List<Scene> m_Scenes = new List<Scene>(); 57 protected List<Scene> m_Scenes = new List<Scene>();
58 58
59 protected IServiceThrottleModule m_ServiceThrottle;
59 // The cache 60 // The cache
60 protected Dictionary<UUID, UserData> m_UserCache = new Dictionary<UUID, UserData>(); 61 protected Dictionary<UUID, UserData> m_UserCache = new Dictionary<UUID, UserData>();
61 62
62 // Throttle the name requests
63 private OpenSim.Framework.BlockingQueue<NameRequest> m_RequestQueue = new OpenSim.Framework.BlockingQueue<NameRequest>();
64
65
66 #region ISharedRegionModule 63 #region ISharedRegionModule
67 64
68 public void Initialise(IConfigSource config) 65 public void Initialise(IConfigSource config)
@@ -115,6 +112,8 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
115 112
116 public void RegionLoaded(Scene s) 113 public void RegionLoaded(Scene s)
117 { 114 {
115 if (m_Enabled && m_ServiceThrottle == null)
116 m_ServiceThrottle = s.RequestModuleInterface<IServiceThrottleModule>();
118 } 117 }
119 118
120 public void PostInitialise() 119 public void PostInitialise()
@@ -154,7 +153,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
154 client.OnAvatarPickerRequest -= new AvatarPickerRequest(HandleAvatarPickerRequest); 153 client.OnAvatarPickerRequest -= new AvatarPickerRequest(HandleAvatarPickerRequest);
155 } 154 }
156 155
157 void HandleUUIDNameRequest(UUID uuid, IClientAPI remote_client) 156 void HandleUUIDNameRequest(UUID uuid, IClientAPI client)
158 { 157 {
159// m_log.DebugFormat( 158// m_log.DebugFormat(
160// "[USER MANAGEMENT MODULE]: Handling request for name binding of UUID {0} from {1}", 159// "[USER MANAGEMENT MODULE]: Handling request for name binding of UUID {0} from {1}",
@@ -162,12 +161,31 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
162 161
163 if (m_Scenes[0].LibraryService != null && (m_Scenes[0].LibraryService.LibraryRootFolder.Owner == uuid)) 162 if (m_Scenes[0].LibraryService != null && (m_Scenes[0].LibraryService.LibraryRootFolder.Owner == uuid))
164 { 163 {
165 remote_client.SendNameReply(uuid, "Mr", "OpenSim"); 164 client.SendNameReply(uuid, "Mr", "OpenSim");
166 } 165 }
167 else 166 else
168 { 167 {
169 NameRequest request = new NameRequest(remote_client, uuid); 168 string[] names = new string[2];
170 m_RequestQueue.Enqueue(request); 169 if (TryGetUserNamesFromCache(uuid, names))
170 {
171 client.SendNameReply(uuid, names[0], names[1]);
172 return;
173 }
174
175 // Not found in cache, queue continuation
176 m_ServiceThrottle.Enqueue("name", uuid.ToString(), delegate
177 {
178 //m_log.DebugFormat("[YYY]: Name request {0}", uuid);
179 bool foundRealName = TryGetUserNames(uuid, names);
180
181 if (names.Length == 2)
182 {
183 if (!foundRealName)
184 m_log.DebugFormat("[USER MANAGEMENT MODULE]: Sending {0} {1} for {2} to {3} since no bound name found", names[0], names[1], uuid, client.Name);
185
186 client.SendNameReply(uuid, names[0], names[1]);
187 }
188 });
171 189
172 } 190 }
173 } 191 }
@@ -283,15 +301,27 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
283 } 301 }
284 302
285 /// <summary> 303 /// <summary>
286 /// Try to get the names bound to the given uuid. 304 ///
287 /// </summary> 305 /// </summary>
288 /// <returns>True if the name was found, false if not.</returns> 306 /// <param name="uuid"></param>
289 /// <param name='uuid'></param> 307 /// <param name="names">Caller please provide a properly instantiated array for names, string[2]</param>
290 /// <param name='names'>The array of names if found. If not found, then names[0] = "Unknown" and names[1] = "User"</param> 308 /// <returns></returns>
291 private bool TryGetUserNames(UUID uuid, out string[] names) 309 private bool TryGetUserNames(UUID uuid, string[] names)
292 { 310 {
293 names = new string[2]; 311 if (names == null)
312 names = new string[2];
313
314 if (TryGetUserNamesFromCache(uuid, names))
315 return true;
316
317 if (TryGetUserNamesFromServices(uuid, names))
318 return true;
319
320 return false;
321 }
294 322
323 private bool TryGetUserNamesFromCache(UUID uuid, string[] names)
324 {
295 lock (m_UserCache) 325 lock (m_UserCache)
296 { 326 {
297 if (m_UserCache.ContainsKey(uuid)) 327 if (m_UserCache.ContainsKey(uuid))
@@ -303,6 +333,17 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
303 } 333 }
304 } 334 }
305 335
336 return false;
337 }
338
339 /// <summary>
340 /// Try to get the names bound to the given uuid, from the services.
341 /// </summary>
342 /// <returns>True if the name was found, false if not.</returns>
343 /// <param name='uuid'></param>
344 /// <param name='names'>The array of names if found. If not found, then names[0] = "Unknown" and names[1] = "User"</param>
345 private bool TryGetUserNamesFromServices(UUID uuid, string[] names)
346 {
306 UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(UUID.Zero, uuid); 347 UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(UUID.Zero, uuid);
307 348
308 if (account != null) 349 if (account != null)
@@ -387,18 +428,11 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
387 428
388 public string GetUserName(UUID uuid) 429 public string GetUserName(UUID uuid)
389 { 430 {
390 string[] names; 431 string[] names = new string[2];
391 TryGetUserNames(uuid, out names); 432 TryGetUserNames(uuid, names);
392 433
393 if (names.Length == 2) 434 return names[0] + " " + names[1];
394 {
395 string firstname = names[0];
396 string lastname = names[1];
397
398 return firstname + " " + lastname;
399 }
400 435
401 return "(hippos)";
402 } 436 }
403 437
404 public string GetUserHomeURL(UUID userID) 438 public string GetUserHomeURL(UUID userID)
@@ -598,13 +632,6 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
598 protected void Init() 632 protected void Init()
599 { 633 {
600 RegisterConsoleCmds(); 634 RegisterConsoleCmds();
601 Watchdog.StartThread(
602 ProcessQueue,
603 "NameRequestThread",
604 ThreadPriority.BelowNormal,
605 true,
606 false);
607
608 } 635 }
609 636
610 protected void RegisterConsoleCmds() 637 protected void RegisterConsoleCmds()
@@ -674,39 +701,6 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
674 MainConsole.Instance.Output(cdt.ToString()); 701 MainConsole.Instance.Output(cdt.ToString());
675 } 702 }
676 703
677 private void ProcessQueue()
678 {
679 while (true)
680 {
681 Watchdog.UpdateThread();
682
683 NameRequest request = m_RequestQueue.Dequeue();
684 string[] names;
685 bool foundRealName = TryGetUserNames(request.uuid, out names);
686
687 if (names.Length == 2)
688 {
689 if (!foundRealName)
690 m_log.DebugFormat("[USER MANAGEMENT MODULE]: Sending {0} {1} for {2} to {3} since no bound name found", names[0], names[1], request.uuid, request.client.Name);
691
692 request.client.SendNameReply(request.uuid, names[0], names[1]);
693 }
694
695 }
696 }
697
698 }
699
700 class NameRequest
701 {
702 public IClientAPI client;
703 public UUID uuid;
704
705 public NameRequest(IClientAPI c, UUID n)
706 {
707 client = c;
708 uuid = n;
709 }
710 } 704 }
711 705
712} \ No newline at end of file 706} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
index 2a4d440..1983fed 100644
--- a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
@@ -219,7 +219,8 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
219 219
220 string uri = "/lslhttp/" + urlcode.ToString(); 220 string uri = "/lslhttp/" + urlcode.ToString();
221 221
222 PollServiceEventArgs args = new PollServiceEventArgs(HttpRequestHandler, HasEvents, GetEvents, NoEvents, urlcode, 25000); 222 PollServiceEventArgs args
223 = new PollServiceEventArgs(HttpRequestHandler, uri, HasEvents, GetEvents, NoEvents, urlcode, 25000);
223 args.Type = PollServiceEventArgs.EventType.LslHttp; 224 args.Type = PollServiceEventArgs.EventType.LslHttp;
224 m_HttpServer.AddPollServiceHTTPHandler(uri, args); 225 m_HttpServer.AddPollServiceHTTPHandler(uri, args);
225 226
@@ -266,7 +267,8 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
266 267
267 string uri = "/lslhttps/" + urlcode.ToString(); 268 string uri = "/lslhttps/" + urlcode.ToString();
268 269
269 PollServiceEventArgs args = new PollServiceEventArgs(HttpRequestHandler, HasEvents, GetEvents, NoEvents, urlcode, 25000); 270 PollServiceEventArgs args
271 = new PollServiceEventArgs(HttpRequestHandler, uri, HasEvents, GetEvents, NoEvents, urlcode, 25000);
270 args.Type = PollServiceEventArgs.EventType.LslHttp; 272 args.Type = PollServiceEventArgs.EventType.LslHttp;
271 m_HttpsServer.AddPollServiceHTTPHandler(uri, args); 273 m_HttpsServer.AddPollServiceHTTPHandler(uri, args);
272 274
diff --git a/OpenSim/Region/Framework/Interfaces/IServiceThrottleModule.cs b/OpenSim/Region/Framework/Interfaces/IServiceThrottleModule.cs
new file mode 100644
index 0000000..198256f
--- /dev/null
+++ b/OpenSim/Region/Framework/Interfaces/IServiceThrottleModule.cs
@@ -0,0 +1,19 @@
1using System;
2using System.Collections.Generic;
3
4namespace OpenSim.Region.Framework.Interfaces
5{
6 public interface IServiceThrottleModule
7 {
8 /// <summary>
9 /// Enqueue a continuation meant to get a resource from elsewhere.
10 /// As usual with CPS, caller beware: if that continuation is a never-ending computation,
11 /// the whole thread will be blocked, and no requests are processed
12 /// </summary>
13 /// <param name="category">Category of the resource (e.g. name, region)</param>
14 /// <param name="itemid">The resource identifier</param>
15 /// <param name="continuation">The continuation to be executed</param>
16 void Enqueue(string category, string itemid, Action continuation);
17 }
18
19}
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
index 8c9c006..b0a29c0 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
@@ -116,7 +116,8 @@ namespace OpenSim.Region.OptionalModules.World.NPC
116 return false; 116 return false;
117 117
118 // Delete existing npc attachments 118 // Delete existing npc attachments
119 scene.AttachmentsModule.DeleteAttachmentsFromScene(npc, false); 119 if(scene.AttachmentsModule != null)
120 scene.AttachmentsModule.DeleteAttachmentsFromScene(npc, false);
120 121
121 // XXX: We can't just use IAvatarFactoryModule.SetAppearance() yet 122 // XXX: We can't just use IAvatarFactoryModule.SetAppearance() yet
122 // since it doesn't transfer attachments 123 // since it doesn't transfer attachments
@@ -125,7 +126,8 @@ namespace OpenSim.Region.OptionalModules.World.NPC
125 npc.Appearance = npcAppearance; 126 npc.Appearance = npcAppearance;
126 127
127 // Rez needed npc attachments 128 // Rez needed npc attachments
128 scene.AttachmentsModule.RezAttachments(npc); 129 if (scene.AttachmentsModule != null)
130 scene.AttachmentsModule.RezAttachments(npc);
129 131
130 IAvatarFactoryModule module = 132 IAvatarFactoryModule module =
131 scene.RequestModuleInterface<IAvatarFactoryModule>(); 133 scene.RequestModuleInterface<IAvatarFactoryModule>();
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs
index 928b350..0f11c4a 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs
@@ -130,6 +130,7 @@ public class BSActorAvatarMove : BSActor
130 SetVelocityAndTarget(m_controllingPrim.RawVelocity, m_controllingPrim.TargetVelocity, true /* inTaintTime */); 130 SetVelocityAndTarget(m_controllingPrim.RawVelocity, m_controllingPrim.TargetVelocity, true /* inTaintTime */);
131 131
132 m_physicsScene.BeforeStep += Mover; 132 m_physicsScene.BeforeStep += Mover;
133 m_controllingPrim.OnPreUpdateProperty += Process_OnPreUpdateProperty;
133 134
134 m_walkingUpStairs = 0; 135 m_walkingUpStairs = 0;
135 } 136 }
@@ -139,6 +140,7 @@ public class BSActorAvatarMove : BSActor
139 { 140 {
140 if (m_velocityMotor != null) 141 if (m_velocityMotor != null)
141 { 142 {
143 m_controllingPrim.OnPreUpdateProperty -= Process_OnPreUpdateProperty;
142 m_physicsScene.BeforeStep -= Mover; 144 m_physicsScene.BeforeStep -= Mover;
143 m_velocityMotor = null; 145 m_velocityMotor = null;
144 } 146 }
@@ -197,7 +199,7 @@ public class BSActorAvatarMove : BSActor
197 { 199 {
198 if (m_controllingPrim.Flying) 200 if (m_controllingPrim.Flying)
199 { 201 {
200 // Flying and not collising and velocity nearly zero. 202 // Flying and not colliding and velocity nearly zero.
201 m_controllingPrim.ZeroMotion(true /* inTaintTime */); 203 m_controllingPrim.ZeroMotion(true /* inTaintTime */);
202 } 204 }
203 } 205 }
@@ -266,6 +268,19 @@ public class BSActorAvatarMove : BSActor
266 } 268 }
267 } 269 }
268 270
271 // Called just as the property update is received from the physics engine.
272 // Do any mode necessary for avatar movement.
273 private void Process_OnPreUpdateProperty(ref EntityProperties entprop)
274 {
275 // Don't change position if standing on a stationary object.
276 if (m_controllingPrim.IsStationary)
277 {
278 entprop.Position = m_controllingPrim.RawPosition;
279 m_physicsScene.PE.SetTranslation(m_controllingPrim.PhysBody, entprop.Position, entprop.Rotation);
280 }
281
282 }
283
269 // Decide if the character is colliding with a low object and compute a force to pop the 284 // Decide if the character is colliding with a low object and compute a force to pop the
270 // avatar up so it can walk up and over the low objects. 285 // avatar up so it can walk up and over the low objects.
271 private OMV.Vector3 WalkUpStairs() 286 private OMV.Vector3 WalkUpStairs()
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index c9e3ca0..59e7f5f 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -709,10 +709,10 @@ public sealed class BSCharacter : BSPhysObject
709 // the world that things have changed. 709 // the world that things have changed.
710 public override void UpdateProperties(EntityProperties entprop) 710 public override void UpdateProperties(EntityProperties entprop)
711 { 711 {
712 // Don't change position if standing on a stationary object. 712 // Let anyone (like the actors) modify the updated properties before they are pushed into the object and the simulator.
713 if (!IsStationary) 713 TriggerPreUpdatePropertyAction(ref entprop);
714 RawPosition = entprop.Position;
715 714
715 RawPosition = entprop.Position;
716 RawOrientation = entprop.Rotation; 716 RawOrientation = entprop.Rotation;
717 717
718 // Smooth velocity. OpenSimulator is VERY sensitive to changes in velocity of the avatar 718 // Smooth velocity. OpenSimulator is VERY sensitive to changes in velocity of the avatar
@@ -740,7 +740,7 @@ public sealed class BSCharacter : BSPhysObject
740 // Linkset.UpdateProperties(UpdatedProperties.EntPropUpdates, this); 740 // Linkset.UpdateProperties(UpdatedProperties.EntPropUpdates, this);
741 741
742 // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop. 742 // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop.
743 // base.RequestPhysicsterseUpdate(); 743 // PhysScene.PostUpdate(this);
744 744
745 DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", 745 DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
746 LocalID, RawPosition, RawOrientation, RawVelocity, _acceleration, _rotationalVelocity); 746 LocalID, RawPosition, RawOrientation, RawVelocity, _acceleration, _rotationalVelocity);
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
index a41eaf8..fc4545f 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
@@ -103,9 +103,10 @@ public abstract class BSPhysObject : PhysicsActor
103 CollisionsLastTickStep = -1; 103 CollisionsLastTickStep = -1;
104 104
105 SubscribedEventsMs = 0; 105 SubscribedEventsMs = 0;
106 CollidingStep = 0; 106 // Crazy values that will never be true
107 CollidingGroundStep = 0; 107 CollidingStep = BSScene.NotASimulationStep;
108 CollisionAccumulation = 0; 108 CollidingGroundStep = BSScene.NotASimulationStep;
109 CollisionAccumulation = BSScene.NotASimulationStep;
109 ColliderIsMoving = false; 110 ColliderIsMoving = false;
110 CollisionScore = 0; 111 CollisionScore = 0;
111 112
@@ -349,7 +350,7 @@ public abstract class BSPhysObject : PhysicsActor
349 if (value) 350 if (value)
350 CollidingStep = PhysScene.SimulationStep; 351 CollidingStep = PhysScene.SimulationStep;
351 else 352 else
352 CollidingStep = 0; 353 CollidingStep = BSScene.NotASimulationStep;
353 } 354 }
354 } 355 }
355 public override bool CollidingGround { 356 public override bool CollidingGround {
@@ -359,7 +360,7 @@ public abstract class BSPhysObject : PhysicsActor
359 if (value) 360 if (value)
360 CollidingGroundStep = PhysScene.SimulationStep; 361 CollidingGroundStep = PhysScene.SimulationStep;
361 else 362 else
362 CollidingGroundStep = 0; 363 CollidingGroundStep = BSScene.NotASimulationStep;
363 } 364 }
364 } 365 }
365 public override bool CollidingObj { 366 public override bool CollidingObj {
@@ -368,7 +369,7 @@ public abstract class BSPhysObject : PhysicsActor
368 if (value) 369 if (value)
369 CollidingObjectStep = PhysScene.SimulationStep; 370 CollidingObjectStep = PhysScene.SimulationStep;
370 else 371 else
371 CollidingObjectStep = 0; 372 CollidingObjectStep = BSScene.NotASimulationStep;
372 } 373 }
373 } 374 }
374 375
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index 214271b..41aca3b 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -97,6 +97,9 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
97 97
98 internal long m_simulationStep = 0; // The current simulation step. 98 internal long m_simulationStep = 0; // The current simulation step.
99 public long SimulationStep { get { return m_simulationStep; } } 99 public long SimulationStep { get { return m_simulationStep; } }
100 // A number to use for SimulationStep that is probably not any step value
101 // Used by the collision code (which remembers the step when a collision happens) to remember not any simulation step.
102 public static long NotASimulationStep = -1234;
100 103
101 internal float LastTimeStep { get; private set; } // The simulation time from the last invocation of Simulate() 104 internal float LastTimeStep { get; private set; } // The simulation time from the last invocation of Simulate()
102 105
diff --git a/OpenSim/Region/RegionCombinerModule/RegionCombinerIndividualEventForwarder.cs b/OpenSim/Region/RegionCombinerModule/RegionCombinerIndividualEventForwarder.cs
index f424e7f..83732e2 100644
--- a/OpenSim/Region/RegionCombinerModule/RegionCombinerIndividualEventForwarder.cs
+++ b/OpenSim/Region/RegionCombinerModule/RegionCombinerIndividualEventForwarder.cs
@@ -51,7 +51,8 @@ namespace OpenSim.Region.RegionCombinerModule
51 m_virtScene.UnSubscribeToClientPrimEvents(client); 51 m_virtScene.UnSubscribeToClientPrimEvents(client);
52 m_virtScene.UnSubscribeToClientPrimRezEvents(client); 52 m_virtScene.UnSubscribeToClientPrimRezEvents(client);
53 m_virtScene.UnSubscribeToClientInventoryEvents(client); 53 m_virtScene.UnSubscribeToClientInventoryEvents(client);
54 ((AttachmentsModule)m_virtScene.AttachmentsModule).UnsubscribeFromClientEvents(client); 54 if(m_virtScene.AttachmentsModule != null)
55 ((AttachmentsModule)m_virtScene.AttachmentsModule).UnsubscribeFromClientEvents(client);
55 //m_virtScene.UnSubscribeToClientTeleportEvents(client); 56 //m_virtScene.UnSubscribeToClientTeleportEvents(client);
56 m_virtScene.UnSubscribeToClientScriptEvents(client); 57 m_virtScene.UnSubscribeToClientScriptEvents(client);
57 58
@@ -66,7 +67,8 @@ namespace OpenSim.Region.RegionCombinerModule
66 client.OnRezObject += LocalRezObject; 67 client.OnRezObject += LocalRezObject;
67 68
68 m_rootScene.SubscribeToClientInventoryEvents(client); 69 m_rootScene.SubscribeToClientInventoryEvents(client);
69 ((AttachmentsModule)m_rootScene.AttachmentsModule).SubscribeToClientEvents(client); 70 if (m_rootScene.AttachmentsModule != null)
71 ((AttachmentsModule)m_rootScene.AttachmentsModule).SubscribeToClientEvents(client);
70 //m_rootScene.SubscribeToClientTeleportEvents(client); 72 //m_rootScene.SubscribeToClientTeleportEvents(client);
71 m_rootScene.SubscribeToClientScriptEvents(client); 73 m_rootScene.SubscribeToClientScriptEvents(client);
72 74