diff options
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden')
-rw-r--r-- | OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs | 194 |
1 files changed, 115 insertions, 79 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs index ddae267..b0d30b6 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs | |||
@@ -176,27 +176,6 @@ namespace OpenSim.Region.ClientStack.Linden | |||
176 | } | 176 | } |
177 | 177 | ||
178 | /// <summary> | 178 | /// <summary> |
179 | /// Always returns a valid queue | ||
180 | /// </summary> | ||
181 | /// <param name="agentId"></param> | ||
182 | /// <returns></returns> | ||
183 | private Queue<OSD> TryGetQueue(UUID agentId) | ||
184 | { | ||
185 | lock (queues) | ||
186 | { | ||
187 | if (!queues.ContainsKey(agentId)) | ||
188 | { | ||
189 | m_log.DebugFormat( | ||
190 | "[EVENTQUEUE]: Adding new queue for agent {0} in region {1}", | ||
191 | agentId, m_scene.RegionInfo.RegionName); | ||
192 | queues[agentId] = new Queue<OSD>(); | ||
193 | } | ||
194 | |||
195 | return queues[agentId]; | ||
196 | } | ||
197 | } | ||
198 | |||
199 | /// <summary> | ||
200 | /// May return a null queue | 179 | /// May return a null queue |
201 | /// </summary> | 180 | /// </summary> |
202 | /// <param name="agentId"></param> | 181 | /// <param name="agentId"></param> |
@@ -278,47 +257,95 @@ namespace OpenSim.Region.ClientStack.Linden | |||
278 | public void OnRegisterCaps(UUID agentID, Caps caps) | 257 | public void OnRegisterCaps(UUID agentID, Caps caps) |
279 | { | 258 | { |
280 | // Register an event queue for the client | 259 | // Register an event queue for the client |
281 | |||
282 | m_log.DebugFormat( | 260 | m_log.DebugFormat( |
283 | "[EVENTQUEUE]: OnRegisterCaps: agentID {0} caps {1} region {2}", | 261 | "[EVENTQUEUE]: OnRegisterCaps: agentID {0} caps {1} region {2}", |
284 | agentID, caps, m_scene.RegionInfo.RegionName); | 262 | agentID, caps, m_scene.RegionInfo.RegionName); |
285 | 263 | ||
286 | // Let's instantiate a Queue for this agent right now | ||
287 | TryGetQueue(agentID); | ||
288 | |||
289 | UUID eventQueueGetUUID; | 264 | UUID eventQueueGetUUID; |
265 | Queue<OSD> queue; | ||
266 | Random rnd = new Random(Environment.TickCount); | ||
267 | int nrnd = rnd.Next(30000000); | ||
268 | if (nrnd < 0) | ||
269 | nrnd = -nrnd; | ||
290 | 270 | ||
291 | lock (m_AvatarQueueUUIDMapping) | 271 | lock (queues) |
292 | { | 272 | { |
293 | // Reuse open queues. The client does! | 273 | if (queues.ContainsKey(agentID)) |
294 | // Its reuse caps path not queues those are been reused already | 274 | queue = queues[agentID]; |
295 | if (m_AvatarQueueUUIDMapping.ContainsKey(agentID)) | 275 | else |
276 | queue = null; | ||
277 | |||
278 | if (queue == null) | ||
296 | { | 279 | { |
297 | m_log.DebugFormat("[EVENTQUEUE]: Found Existing UUID!"); | 280 | queue = new Queue<OSD>(); |
298 | eventQueueGetUUID = m_AvatarQueueUUIDMapping[agentID]; | 281 | queues[agentID] = queue; |
282 | |||
283 | // push markers to handle old responses still waiting | ||
284 | // this will cost at most viewer getting two forced noevents | ||
285 | // even being a new queue better be safe | ||
286 | queue.Enqueue(null); | ||
287 | queue.Enqueue(null); // one should be enough | ||
288 | |||
289 | lock (m_AvatarQueueUUIDMapping) | ||
290 | { | ||
291 | eventQueueGetUUID = UUID.Random(); | ||
292 | if (m_AvatarQueueUUIDMapping.ContainsKey(agentID)) | ||
293 | { | ||
294 | // oops this should not happen ? | ||
295 | m_log.DebugFormat("[EVENTQUEUE]: Found Existing UUID without a queue"); | ||
296 | eventQueueGetUUID = m_AvatarQueueUUIDMapping[agentID]; | ||
297 | } | ||
298 | m_AvatarQueueUUIDMapping.Add(agentID, eventQueueGetUUID); | ||
299 | } | ||
300 | lock (m_ids) | ||
301 | { | ||
302 | if (!m_ids.ContainsKey(agentID)) | ||
303 | m_ids.Add(agentID, nrnd); | ||
304 | else | ||
305 | m_ids[agentID] = nrnd; | ||
306 | } | ||
299 | } | 307 | } |
300 | else | 308 | else |
301 | { | 309 | { |
302 | eventQueueGetUUID = UUID.Random(); | 310 | // push markers to handle old responses still waiting |
303 | m_AvatarQueueUUIDMapping.Add(agentID, eventQueueGetUUID); | 311 | // this will cost at most viewer getting two forced noevents |
304 | m_log.DebugFormat("[EVENTQUEUE]: Using random UUID!"); | 312 | // even being a new queue better be safe |
313 | queue.Enqueue(null); | ||
314 | queue.Enqueue(null); // one should be enough | ||
315 | |||
316 | // reuse or not to reuse TODO FIX | ||
317 | lock (m_AvatarQueueUUIDMapping) | ||
318 | { | ||
319 | // Reuse open queues. The client does! | ||
320 | // Its reuse caps path not queues those are been reused already | ||
321 | if (m_AvatarQueueUUIDMapping.ContainsKey(agentID)) | ||
322 | { | ||
323 | m_log.DebugFormat("[EVENTQUEUE]: Found Existing UUID!"); | ||
324 | eventQueueGetUUID = m_AvatarQueueUUIDMapping[agentID]; | ||
325 | } | ||
326 | else | ||
327 | { | ||
328 | eventQueueGetUUID = UUID.Random(); | ||
329 | m_AvatarQueueUUIDMapping.Add(agentID, eventQueueGetUUID); | ||
330 | m_log.DebugFormat("[EVENTQUEUE]: Using random UUID!"); | ||
331 | } | ||
332 | } | ||
333 | lock (m_ids) | ||
334 | { | ||
335 | // change to negative numbers so they are changed at end of sending first marker | ||
336 | // old data on a queue may be sent on a response for a new caps | ||
337 | // but at least will be sent with coerent IDs | ||
338 | if (!m_ids.ContainsKey(agentID)) | ||
339 | m_ids.Add(agentID, -nrnd); // should not happen | ||
340 | else | ||
341 | m_ids[agentID] = -m_ids[agentID]; | ||
342 | } | ||
305 | } | 343 | } |
306 | } | 344 | } |
307 | 345 | ||
308 | caps.RegisterPollHandler( | 346 | caps.RegisterPollHandler( |
309 | "EventQueueGet", | 347 | "EventQueueGet", |
310 | new PollServiceEventArgs(null, GenerateEqgCapPath(eventQueueGetUUID), HasEvents, GetEvents, NoEvents, agentID, SERVER_EQ_TIME_NO_EVENTS)); | 348 | new PollServiceEventArgs(null, GenerateEqgCapPath(eventQueueGetUUID), HasEvents, GetEvents, NoEvents, agentID, SERVER_EQ_TIME_NO_EVENTS)); |
311 | |||
312 | Random rnd = new Random(Environment.TickCount); | ||
313 | int nrnd = rnd.Next(30000000); | ||
314 | |||
315 | lock (m_ids) | ||
316 | { | ||
317 | if (!m_ids.ContainsKey(agentID)) | ||
318 | m_ids.Add(agentID, nrnd); | ||
319 | else | ||
320 | m_ids[agentID] = nrnd; | ||
321 | } | ||
322 | } | 349 | } |
323 | 350 | ||
324 | public bool HasEvents(UUID requestID, UUID agentID) | 351 | public bool HasEvents(UUID requestID, UUID agentID) |
@@ -361,55 +388,65 @@ namespace OpenSim.Region.ClientStack.Linden | |||
361 | return NoEvents(requestID, pAgentId); | 388 | return NoEvents(requestID, pAgentId); |
362 | } | 389 | } |
363 | 390 | ||
364 | OSD element; | 391 | OSD element = null;; |
392 | OSDArray array = new OSDArray(); | ||
393 | int thisID = 0; | ||
394 | bool negativeID = false; | ||
395 | |||
365 | lock (queue) | 396 | lock (queue) |
366 | { | 397 | { |
367 | if (queue.Count == 0) | 398 | if (queue.Count == 0) |
368 | return NoEvents(requestID, pAgentId); | 399 | return NoEvents(requestID, pAgentId); |
369 | element = queue.Dequeue(); // 15s timeout | ||
370 | } | ||
371 | |||
372 | int thisID = 0; | ||
373 | lock (m_ids) | ||
374 | thisID = m_ids[pAgentId]; | ||
375 | |||
376 | OSDArray array = new OSDArray(); | ||
377 | if (element == null) // didn't have an event in 15s | ||
378 | { | ||
379 | // Send it a fake event to keep the client polling! It doesn't like 502s like the proxys say! | ||
380 | array.Add(EventQueueHelper.KeepAliveEvent()); | ||
381 | //m_log.DebugFormat("[EVENTQUEUE]: adding fake event for {0} in region {1}", pAgentId, m_scene.RegionInfo.RegionName); | ||
382 | } | ||
383 | else | ||
384 | { | ||
385 | if (DebugLevel > 0) | ||
386 | LogOutboundDebugMessage(element, pAgentId); | ||
387 | 400 | ||
388 | array.Add(element); | 401 | lock (m_ids) |
402 | thisID = m_ids[pAgentId]; | ||
389 | 403 | ||
390 | lock (queue) | 404 | if (thisID < 0) |
391 | { | 405 | { |
392 | while (queue.Count > 0) | 406 | negativeID = true; |
393 | { | 407 | thisID = -thisID; |
394 | element = queue.Dequeue(); | 408 | } |
409 | |||
410 | while (queue.Count > 0) | ||
411 | { | ||
412 | element = queue.Dequeue(); | ||
413 | // add elements until a marker is found | ||
414 | // so they get into a response | ||
415 | if (element == null) | ||
416 | break; | ||
417 | if (DebugLevel > 0) | ||
418 | LogOutboundDebugMessage(element, pAgentId); | ||
419 | array.Add(element); | ||
420 | thisID++; | ||
421 | } | ||
422 | } | ||
395 | 423 | ||
396 | if (DebugLevel > 0) | 424 | OSDMap events = null; |
397 | LogOutboundDebugMessage(element, pAgentId); | ||
398 | 425 | ||
399 | array.Add(element); | 426 | if (array.Count > 0) |
400 | thisID++; | 427 | { |
401 | } | 428 | events = new OSDMap(); |
402 | } | 429 | events.Add("events", array); |
430 | events.Add("id", new OSDInteger(thisID)); | ||
403 | } | 431 | } |
404 | 432 | ||
405 | OSDMap events = new OSDMap(); | 433 | if (negativeID && element == null) |
406 | events.Add("events", array); | 434 | { |
435 | Random rnd = new Random(Environment.TickCount); | ||
436 | thisID = rnd.Next(30000000); | ||
437 | if (thisID < 0) | ||
438 | thisID = -thisID; | ||
439 | } | ||
407 | 440 | ||
408 | events.Add("id", new OSDInteger(thisID)); | ||
409 | lock (m_ids) | 441 | lock (m_ids) |
410 | { | 442 | { |
411 | m_ids[pAgentId] = thisID + 1; | 443 | m_ids[pAgentId] = thisID + 1; |
412 | } | 444 | } |
445 | |||
446 | // if there where no elements before a marker send a NoEvents | ||
447 | if (array.Count == 0) | ||
448 | return NoEvents(requestID, pAgentId); | ||
449 | |||
413 | Hashtable responsedata = new Hashtable(); | 450 | Hashtable responsedata = new Hashtable(); |
414 | responsedata["int_response_code"] = 200; | 451 | responsedata["int_response_code"] = 200; |
415 | responsedata["content_type"] = "application/xml"; | 452 | responsedata["content_type"] = "application/xml"; |
@@ -432,7 +469,6 @@ namespace OpenSim.Region.ClientStack.Linden | |||
432 | responsedata["http_protocol_version"] = "HTTP/1.0"; | 469 | responsedata["http_protocol_version"] = "HTTP/1.0"; |
433 | return responsedata; | 470 | return responsedata; |
434 | } | 471 | } |
435 | |||
436 | 472 | ||
437 | public void DisableSimulator(ulong handle, UUID avatarID) | 473 | public void DisableSimulator(ulong handle, UUID avatarID) |
438 | { | 474 | { |