diff options
author | Justin Clarke Casey | 2008-03-24 19:44:25 +0000 |
---|---|---|
committer | Justin Clarke Casey | 2008-03-24 19:44:25 +0000 |
commit | 45b9114df77e43be95487fbdd2b5739bdf665c1c (patch) | |
tree | f677b731631d0a10f8023113722afb53f48244fc | |
parent | Implements llGetInventoryNumber() (diff) | |
download | opensim-SC_OLD-45b9114df77e43be95487fbdd2b5739bdf665c1c.zip opensim-SC_OLD-45b9114df77e43be95487fbdd2b5739bdf665c1c.tar.gz opensim-SC_OLD-45b9114df77e43be95487fbdd2b5739bdf665c1c.tar.bz2 opensim-SC_OLD-45b9114df77e43be95487fbdd2b5739bdf665c1c.tar.xz |
From: Michael Osias <mosias@us.ibm.com>
Fixes mantis 771 - multiple uses of llListen cause duplicate events
Thanks Michael!
-rw-r--r-- | OpenSim/Region/Environment/Modules/WorldCommModule.cs | 259 |
1 files changed, 146 insertions, 113 deletions
diff --git a/OpenSim/Region/Environment/Modules/WorldCommModule.cs b/OpenSim/Region/Environment/Modules/WorldCommModule.cs index b4e1fef..e1d2fbc 100644 --- a/OpenSim/Region/Environment/Modules/WorldCommModule.cs +++ b/OpenSim/Region/Environment/Modules/WorldCommModule.cs | |||
@@ -26,6 +26,7 @@ | |||
26 | */ | 26 | */ |
27 | 27 | ||
28 | using System; | 28 | using System; |
29 | using System.Collections; | ||
29 | using System.Collections.Generic; | 30 | using System.Collections.Generic; |
30 | using libsecondlife; | 31 | using libsecondlife; |
31 | using Nini.Config; | 32 | using Nini.Config; |
@@ -72,8 +73,8 @@ namespace OpenSim.Region.Environment.Modules | |||
72 | private object ListLock = new object(); | 73 | private object ListLock = new object(); |
73 | private string m_name = "WorldCommModule"; | 74 | private string m_name = "WorldCommModule"; |
74 | private ListenerManager m_listenerManager; | 75 | private ListenerManager m_listenerManager; |
75 | private Queue<ListenerInfo> m_pending; | 76 | private Queue m_pendingQ; |
76 | 77 | private Queue m_pending; | |
77 | public WorldCommModule() | 78 | public WorldCommModule() |
78 | { | 79 | { |
79 | } | 80 | } |
@@ -84,7 +85,8 @@ namespace OpenSim.Region.Environment.Modules | |||
84 | m_scene.RegisterModuleInterface<IWorldComm>(this); | 85 | m_scene.RegisterModuleInterface<IWorldComm>(this); |
85 | m_listenerManager = new ListenerManager(); | 86 | m_listenerManager = new ListenerManager(); |
86 | m_scene.EventManager.OnNewClient += NewClient; | 87 | m_scene.EventManager.OnNewClient += NewClient; |
87 | m_pending = new Queue<ListenerInfo>(); | 88 | m_pendingQ = new Queue(); |
89 | m_pending = Queue.Synchronized(m_pendingQ); | ||
88 | } | 90 | } |
89 | 91 | ||
90 | public void PostInitialise() | 92 | public void PostInitialise() |
@@ -125,27 +127,29 @@ namespace OpenSim.Region.Environment.Modules | |||
125 | 127 | ||
126 | public void ListenControl(int handle, int active) | 128 | public void ListenControl(int handle, int active) |
127 | { | 129 | { |
128 | if (active == 1) | 130 | if (m_listenerManager != null) |
129 | m_listenerManager.Activate(handle); | 131 | { |
130 | else if (active == 0) | 132 | if (active == 1) |
131 | m_listenerManager.Dectivate(handle); | 133 | m_listenerManager.Activate(handle); |
134 | else if (active == 0) | ||
135 | m_listenerManager.Dectivate(handle); | ||
136 | } | ||
132 | } | 137 | } |
133 | 138 | ||
134 | public void ListenRemove(int handle) | 139 | public void ListenRemove(int handle) |
135 | { | 140 | { |
136 | m_listenerManager.Remove(handle); | 141 | if (m_listenerManager != null) |
142 | { | ||
143 | m_listenerManager.Remove(handle); | ||
144 | } | ||
137 | } | 145 | } |
138 | 146 | ||
139 | public void DeleteListener(LLUUID itemID) | 147 | public void DeleteListener(LLUUID itemID) |
140 | { | 148 | { |
141 | if (m_listenerManager != null) | 149 | if (m_listenerManager != null) |
142 | { | 150 | { |
143 | lock (ListLock) | 151 | m_listenerManager.DeleteListener(itemID); |
144 | { | ||
145 | m_listenerManager.DeleteListener(itemID); | ||
146 | } | ||
147 | } | 152 | } |
148 | |||
149 | } | 153 | } |
150 | 154 | ||
151 | // This method scans nearby objects and determines if they are listeners, | 155 | // This method scans nearby objects and determines if they are listeners, |
@@ -175,87 +179,99 @@ namespace OpenSim.Region.Environment.Modules | |||
175 | 179 | ||
176 | m_scene.Entities.TryGetValue(li.GetHostID(), out sPart); | 180 | m_scene.Entities.TryGetValue(li.GetHostID(), out sPart); |
177 | 181 | ||
178 | // Dont process if this message is from itself! | 182 | if(sPart != null) |
179 | if (li.GetHostID().ToString().Equals(sourceItemID) || | 183 | { |
180 | sPart.UUID.ToString().Equals(sourceItemID)) | 184 | // Dont process if this message is from itself! |
181 | continue; | 185 | if (li.GetHostID().ToString().Equals(sourceItemID) || |
186 | sPart.UUID.ToString().Equals(sourceItemID)) | ||
187 | continue; | ||
182 | 188 | ||
183 | double dis = 0; | 189 | double dis = 0; |
184 | 190 | ||
185 | if (source != null) | 191 | if (source != null) |
186 | dis = Util.GetDistanceTo(sPart.AbsolutePosition, source.AbsolutePosition); | 192 | dis = Util.GetDistanceTo(sPart.AbsolutePosition, source.AbsolutePosition); |
187 | else | 193 | else |
188 | dis = Util.GetDistanceTo(sPart.AbsolutePosition, avatar.AbsolutePosition); | 194 | dis = Util.GetDistanceTo(sPart.AbsolutePosition, avatar.AbsolutePosition); |
189 | 195 | ||
190 | switch (type) | 196 | switch (type) |
191 | { | 197 | { |
192 | case ChatTypeEnum.Whisper: | 198 | case ChatTypeEnum.Whisper: |
193 | 199 | ||
194 | if ((dis < 10) && (dis > -10)) | 200 | if ((dis < 10) && (dis > -10)) |
195 | { | ||
196 | ListenerInfo isListener = m_listenerManager.IsListenerMatch( | ||
197 | sourceItemID, sPart.UUID, channel, name, msg | ||
198 | ); | ||
199 | if (isListener != null) | ||
200 | { | 201 | { |
201 | lock (CommListLock) | 202 | if (li.GetChannel() == channel) |
202 | { | 203 | { |
203 | m_pending.Enqueue(isListener); | 204 | ListenerInfo isListener = m_listenerManager.IsListenerMatch( |
205 | sourceItemID, sPart.UUID, channel, name, msg | ||
206 | ); | ||
207 | if (isListener != null) | ||
208 | { | ||
209 | lock (m_pending.SyncRoot) | ||
210 | { | ||
211 | m_pending.Enqueue(isListener); | ||
212 | } | ||
213 | } | ||
204 | } | 214 | } |
205 | } | 215 | } |
206 | } | 216 | break; |
207 | break; | ||
208 | 217 | ||
209 | case ChatTypeEnum.Say: | 218 | case ChatTypeEnum.Say: |
210 | 219 | ||
211 | if ((dis < 30) && (dis > -30)) | 220 | if ((dis < 30) && (dis > -30)) |
212 | { | ||
213 | ListenerInfo isListener = m_listenerManager.IsListenerMatch( | ||
214 | sourceItemID, sPart.UUID, channel, name, msg | ||
215 | ); | ||
216 | if (isListener != null) | ||
217 | { | 221 | { |
218 | lock (CommListLock) | 222 | if (li.GetChannel() == channel) |
219 | { | 223 | { |
220 | m_pending.Enqueue(isListener); | 224 | ListenerInfo isListener = m_listenerManager.IsListenerMatch( |
225 | sourceItemID, sPart.UUID, channel, name, msg | ||
226 | ); | ||
227 | if (isListener != null) | ||
228 | { | ||
229 | lock (m_pending.SyncRoot) | ||
230 | { | ||
231 | m_pending.Enqueue(isListener); | ||
232 | } | ||
233 | } | ||
221 | } | 234 | } |
222 | } | 235 | } |
223 | } | 236 | break; |
224 | break; | ||
225 | 237 | ||
226 | case ChatTypeEnum.Shout: | 238 | case ChatTypeEnum.Shout: |
227 | if ((dis < 100) && (dis > -100)) | 239 | if ((dis < 100) && (dis > -100)) |
228 | { | ||
229 | ListenerInfo isListener = m_listenerManager.IsListenerMatch( | ||
230 | sourceItemID, sPart.UUID, channel, name, msg | ||
231 | ); | ||
232 | if (isListener != null) | ||
233 | { | 240 | { |
234 | lock (CommListLock) | 241 | if (li.GetChannel() == channel) |
235 | { | 242 | { |
236 | m_pending.Enqueue(isListener); | 243 | ListenerInfo isListener = m_listenerManager.IsListenerMatch( |
244 | sourceItemID, sPart.UUID, channel, name, msg | ||
245 | ); | ||
246 | if (isListener != null) | ||
247 | { | ||
248 | lock (m_pending.SyncRoot) | ||
249 | { | ||
250 | m_pending.Enqueue(isListener); | ||
251 | } | ||
252 | } | ||
237 | } | 253 | } |
238 | } | 254 | } |
239 | } | 255 | break; |
240 | break; | ||
241 | 256 | ||
242 | case ChatTypeEnum.Broadcast: | 257 | case ChatTypeEnum.Broadcast: |
243 | ListenerInfo isListen = | 258 | ListenerInfo isListen = |
244 | m_listenerManager.IsListenerMatch(sourceItemID, li.GetItemID(), channel, name, msg); | 259 | m_listenerManager.IsListenerMatch(sourceItemID, li.GetItemID(), channel, name, msg); |
245 | if (isListen != null) | 260 | if (isListen != null) |
246 | { | ||
247 | ListenerInfo isListener = m_listenerManager.IsListenerMatch( | ||
248 | sourceItemID, sPart.UUID, channel, name, msg | ||
249 | ); | ||
250 | if (isListener != null) | ||
251 | { | 261 | { |
252 | lock (CommListLock) | 262 | ListenerInfo isListener = m_listenerManager.IsListenerMatch( |
263 | sourceItemID, sPart.UUID, channel, name, msg | ||
264 | ); | ||
265 | if (isListener != null) | ||
253 | { | 266 | { |
254 | m_pending.Enqueue(isListener); | 267 | lock (m_pending.SyncRoot) |
268 | { | ||
269 | m_pending.Enqueue(isListener); | ||
270 | } | ||
255 | } | 271 | } |
256 | } | 272 | } |
257 | } | 273 | break; |
258 | break; | 274 | } |
259 | } | 275 | } |
260 | } | 276 | } |
261 | } | 277 | } |
@@ -273,9 +289,9 @@ namespace OpenSim.Region.Environment.Modules | |||
273 | { | 289 | { |
274 | ListenerInfo li = null; | 290 | ListenerInfo li = null; |
275 | 291 | ||
276 | lock (CommListLock) | 292 | lock (m_pending.SyncRoot) |
277 | { | 293 | { |
278 | li = m_pending.Dequeue(); | 294 | li = (ListenerInfo) m_pending.Dequeue(); |
279 | } | 295 | } |
280 | 296 | ||
281 | return li; | 297 | return li; |
@@ -283,12 +299,12 @@ namespace OpenSim.Region.Environment.Modules | |||
283 | 299 | ||
284 | public uint PeekNextMessageLocalID() | 300 | public uint PeekNextMessageLocalID() |
285 | { | 301 | { |
286 | return m_pending.Peek().GetLocalID(); | 302 | return ((ListenerInfo)m_pending.Peek()).GetLocalID(); |
287 | } | 303 | } |
288 | 304 | ||
289 | public LLUUID PeekNextMessageItemID() | 305 | public LLUUID PeekNextMessageItemID() |
290 | { | 306 | { |
291 | return m_pending.Peek().GetItemID(); | 307 | return ((ListenerInfo)m_pending.Peek()).GetItemID(); |
292 | } | 308 | } |
293 | 309 | ||
294 | } | 310 | } |
@@ -298,15 +314,11 @@ namespace OpenSim.Region.Environment.Modules | |||
298 | // localID: local ID of host engine | 314 | // localID: local ID of host engine |
299 | public class ListenerManager | 315 | public class ListenerManager |
300 | { | 316 | { |
301 | private Dictionary<int, ListenerInfo> m_listeners; | 317 | //private Dictionary<int, ListenerInfo> m_listeners; |
318 | private Hashtable m_listeners = Hashtable.Synchronized(new Hashtable()); | ||
302 | private object ListenersLock = new object(); | 319 | private object ListenersLock = new object(); |
303 | private int m_MaxListeners = 100; | 320 | private int m_MaxListeners = 100; |
304 | 321 | ||
305 | public ListenerManager() | ||
306 | { | ||
307 | m_listeners = new Dictionary<int, ListenerInfo>(); | ||
308 | } | ||
309 | |||
310 | public int AddListener(uint localID, LLUUID itemID, LLUUID hostID, int channel, string name, string id, string msg) | 322 | public int AddListener(uint localID, LLUUID itemID, LLUUID hostID, int channel, string name, string id, string msg) |
311 | { | 323 | { |
312 | if (m_listeners.Count < m_MaxListeners) | 324 | if (m_listeners.Count < m_MaxListeners) |
@@ -321,7 +333,7 @@ namespace OpenSim.Region.Environment.Modules | |||
321 | { | 333 | { |
322 | ListenerInfo li = new ListenerInfo(localID, newHandle, itemID, hostID, channel, name, id, msg); | 334 | ListenerInfo li = new ListenerInfo(localID, newHandle, itemID, hostID, channel, name, id, msg); |
323 | 335 | ||
324 | lock (ListenersLock) | 336 | lock (m_listeners.SyncRoot) |
325 | { | 337 | { |
326 | m_listeners.Add(newHandle, li); | 338 | m_listeners.Add(newHandle, li); |
327 | } | 339 | } |
@@ -336,17 +348,30 @@ namespace OpenSim.Region.Environment.Modules | |||
336 | 348 | ||
337 | public void Remove(int handle) | 349 | public void Remove(int handle) |
338 | { | 350 | { |
339 | m_listeners.Remove(handle); | 351 | lock (m_listeners.SyncRoot) |
352 | { | ||
353 | m_listeners.Remove(handle); | ||
354 | } | ||
340 | } | 355 | } |
341 | 356 | ||
342 | public void DeleteListener(LLUUID itemID) | 357 | public void DeleteListener(LLUUID itemID) |
343 | { | 358 | { |
344 | foreach (ListenerInfo li in m_listeners.Values) | 359 | ArrayList removedListeners = new ArrayList(); |
360 | |||
361 | lock (m_listeners.SyncRoot) | ||
345 | { | 362 | { |
346 | if (li.GetItemID().Equals(itemID)) | 363 | IDictionaryEnumerator en = m_listeners.GetEnumerator(); |
364 | while (en.MoveNext()) | ||
365 | { | ||
366 | ListenerInfo li = (ListenerInfo)en.Value; | ||
367 | if (li.GetItemID().Equals(itemID)) | ||
368 | { | ||
369 | removedListeners.Add(li.GetHandle()); | ||
370 | } | ||
371 | } | ||
372 | foreach (int handle in removedListeners) | ||
347 | { | 373 | { |
348 | Remove(li.GetHandle()); | 374 | m_listeners.Remove(handle); |
349 | return; | ||
350 | } | 375 | } |
351 | } | 376 | } |
352 | } | 377 | } |
@@ -375,20 +400,23 @@ namespace OpenSim.Region.Environment.Modules | |||
375 | 400 | ||
376 | public void Activate(int handle) | 401 | public void Activate(int handle) |
377 | { | 402 | { |
378 | ListenerInfo li; | ||
379 | 403 | ||
380 | if (m_listeners.TryGetValue(handle, out li)) | 404 | if (m_listeners.ContainsKey(handle)) |
381 | { | 405 | { |
382 | li.Activate(); | 406 | lock (m_listeners.SyncRoot) |
407 | { | ||
408 | ListenerInfo li = (ListenerInfo)m_listeners[handle]; | ||
409 | li.Activate(); | ||
410 | } | ||
383 | } | 411 | } |
384 | } | 412 | } |
385 | 413 | ||
386 | public void Dectivate(int handle) | 414 | public void Dectivate(int handle) |
387 | { | 415 | { |
388 | ListenerInfo li; | ||
389 | 416 | ||
390 | if (m_listeners.TryGetValue(handle, out li)) | 417 | if (m_listeners.ContainsKey(handle)) |
391 | { | 418 | { |
419 | ListenerInfo li = (ListenerInfo)m_listeners[handle]; | ||
392 | li.Deactivate(); | 420 | li.Deactivate(); |
393 | } | 421 | } |
394 | } | 422 | } |
@@ -399,36 +427,41 @@ namespace OpenSim.Region.Environment.Modules | |||
399 | string msg) | 427 | string msg) |
400 | { | 428 | { |
401 | bool isMatch = true; | 429 | bool isMatch = true; |
402 | 430 | lock (m_listeners.SyncRoot) | |
403 | foreach (ListenerInfo li in m_listeners.Values) | ||
404 | { | 431 | { |
405 | if (li.GetHostID().Equals(listenerKey)) | 432 | IDictionaryEnumerator en = m_listeners.GetEnumerator(); |
433 | while (en.MoveNext()) | ||
406 | { | 434 | { |
407 | if (li.IsActive()) | 435 | ListenerInfo li = (ListenerInfo)en.Value; |
436 | |||
437 | if (li.GetHostID().Equals(listenerKey)) | ||
408 | { | 438 | { |
409 | if (channel == li.GetChannel()) | 439 | if (li.IsActive()) |
410 | { | 440 | { |
411 | if ((li.GetID().ToString().Length > 0) && | 441 | if (channel == li.GetChannel()) |
412 | (!li.GetID().Equals(LLUUID.Zero))) | ||
413 | { | 442 | { |
414 | if (!li.GetID().ToString().Equals(sourceItemID)) | 443 | if ((li.GetID().ToString().Length > 0) && |
444 | (!li.GetID().Equals(LLUUID.Zero))) | ||
415 | { | 445 | { |
416 | isMatch = false; | 446 | if (!li.GetID().ToString().Equals(sourceItemID)) |
447 | { | ||
448 | isMatch = false; | ||
449 | } | ||
417 | } | 450 | } |
418 | } | 451 | if (isMatch && (li.GetName().Length > 0)) |
419 | if (isMatch && (li.GetName().Length > 0)) | ||
420 | { | ||
421 | if (li.GetName().Equals(name)) | ||
422 | { | 452 | { |
423 | isMatch = false; | 453 | if (li.GetName().Equals(name)) |
454 | { | ||
455 | isMatch = false; | ||
456 | } | ||
457 | } | ||
458 | if (isMatch) | ||
459 | { | ||
460 | return new ListenerInfo( | ||
461 | li.GetLocalID(), li.GetHandle(), li.GetItemID(), li.GetHostID(), | ||
462 | li.GetChannel(), name, li.GetID(), msg, new LLUUID(sourceItemID) | ||
463 | ); | ||
424 | } | 464 | } |
425 | } | ||
426 | if (isMatch) | ||
427 | { | ||
428 | return new ListenerInfo( | ||
429 | li.GetLocalID(), li.GetHandle(), li.GetItemID(), li.GetHostID(), | ||
430 | li.GetChannel(), name, li.GetID(), msg, new LLUUID(sourceItemID) | ||
431 | ); | ||
432 | } | 465 | } |
433 | } | 466 | } |
434 | } | 467 | } |
@@ -437,7 +470,7 @@ namespace OpenSim.Region.Environment.Modules | |||
437 | return null; | 470 | return null; |
438 | } | 471 | } |
439 | 472 | ||
440 | public Dictionary<int, ListenerInfo>.ValueCollection GetListeners() | 473 | public ICollection GetListeners() |
441 | { | 474 | { |
442 | return m_listeners.Values; | 475 | return m_listeners.Values; |
443 | } | 476 | } |