From 70890e211a495c2120c801ac68b21fc3dbf51cbf Mon Sep 17 00:00:00 2001
From: UbitUmarov
Date: Fri, 25 Jul 2014 17:29:41 +0100
Subject: add queue transition code needs review/more testing
---
.../Linden/Caps/EventQueue/EventQueueGetModule.cs | 194 ++++++++++++---------
1 file 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
}
///
- /// Always returns a valid queue
- ///
- ///
- ///
- private Queue TryGetQueue(UUID agentId)
- {
- lock (queues)
- {
- if (!queues.ContainsKey(agentId))
- {
- m_log.DebugFormat(
- "[EVENTQUEUE]: Adding new queue for agent {0} in region {1}",
- agentId, m_scene.RegionInfo.RegionName);
- queues[agentId] = new Queue();
- }
-
- return queues[agentId];
- }
- }
-
- ///
/// May return a null queue
///
///
@@ -278,47 +257,95 @@ namespace OpenSim.Region.ClientStack.Linden
public void OnRegisterCaps(UUID agentID, Caps caps)
{
// Register an event queue for the client
-
m_log.DebugFormat(
"[EVENTQUEUE]: OnRegisterCaps: agentID {0} caps {1} region {2}",
agentID, caps, m_scene.RegionInfo.RegionName);
- // Let's instantiate a Queue for this agent right now
- TryGetQueue(agentID);
-
UUID eventQueueGetUUID;
+ Queue queue;
+ Random rnd = new Random(Environment.TickCount);
+ int nrnd = rnd.Next(30000000);
+ if (nrnd < 0)
+ nrnd = -nrnd;
- lock (m_AvatarQueueUUIDMapping)
+ lock (queues)
{
- // Reuse open queues. The client does!
- // Its reuse caps path not queues those are been reused already
- if (m_AvatarQueueUUIDMapping.ContainsKey(agentID))
+ if (queues.ContainsKey(agentID))
+ queue = queues[agentID];
+ else
+ queue = null;
+
+ if (queue == null)
{
- m_log.DebugFormat("[EVENTQUEUE]: Found Existing UUID!");
- eventQueueGetUUID = m_AvatarQueueUUIDMapping[agentID];
+ queue = new Queue();
+ queues[agentID] = queue;
+
+ // push markers to handle old responses still waiting
+ // this will cost at most viewer getting two forced noevents
+ // even being a new queue better be safe
+ queue.Enqueue(null);
+ queue.Enqueue(null); // one should be enough
+
+ lock (m_AvatarQueueUUIDMapping)
+ {
+ eventQueueGetUUID = UUID.Random();
+ if (m_AvatarQueueUUIDMapping.ContainsKey(agentID))
+ {
+ // oops this should not happen ?
+ m_log.DebugFormat("[EVENTQUEUE]: Found Existing UUID without a queue");
+ eventQueueGetUUID = m_AvatarQueueUUIDMapping[agentID];
+ }
+ m_AvatarQueueUUIDMapping.Add(agentID, eventQueueGetUUID);
+ }
+ lock (m_ids)
+ {
+ if (!m_ids.ContainsKey(agentID))
+ m_ids.Add(agentID, nrnd);
+ else
+ m_ids[agentID] = nrnd;
+ }
}
else
{
- eventQueueGetUUID = UUID.Random();
- m_AvatarQueueUUIDMapping.Add(agentID, eventQueueGetUUID);
- m_log.DebugFormat("[EVENTQUEUE]: Using random UUID!");
+ // push markers to handle old responses still waiting
+ // this will cost at most viewer getting two forced noevents
+ // even being a new queue better be safe
+ queue.Enqueue(null);
+ queue.Enqueue(null); // one should be enough
+
+ // reuse or not to reuse TODO FIX
+ lock (m_AvatarQueueUUIDMapping)
+ {
+ // Reuse open queues. The client does!
+ // Its reuse caps path not queues those are been reused already
+ if (m_AvatarQueueUUIDMapping.ContainsKey(agentID))
+ {
+ m_log.DebugFormat("[EVENTQUEUE]: Found Existing UUID!");
+ eventQueueGetUUID = m_AvatarQueueUUIDMapping[agentID];
+ }
+ else
+ {
+ eventQueueGetUUID = UUID.Random();
+ m_AvatarQueueUUIDMapping.Add(agentID, eventQueueGetUUID);
+ m_log.DebugFormat("[EVENTQUEUE]: Using random UUID!");
+ }
+ }
+ lock (m_ids)
+ {
+ // change to negative numbers so they are changed at end of sending first marker
+ // old data on a queue may be sent on a response for a new caps
+ // but at least will be sent with coerent IDs
+ if (!m_ids.ContainsKey(agentID))
+ m_ids.Add(agentID, -nrnd); // should not happen
+ else
+ m_ids[agentID] = -m_ids[agentID];
+ }
}
}
caps.RegisterPollHandler(
"EventQueueGet",
new PollServiceEventArgs(null, GenerateEqgCapPath(eventQueueGetUUID), HasEvents, GetEvents, NoEvents, agentID, SERVER_EQ_TIME_NO_EVENTS));
-
- Random rnd = new Random(Environment.TickCount);
- int nrnd = rnd.Next(30000000);
-
- lock (m_ids)
- {
- if (!m_ids.ContainsKey(agentID))
- m_ids.Add(agentID, nrnd);
- else
- m_ids[agentID] = nrnd;
- }
}
public bool HasEvents(UUID requestID, UUID agentID)
@@ -361,55 +388,65 @@ namespace OpenSim.Region.ClientStack.Linden
return NoEvents(requestID, pAgentId);
}
- OSD element;
+ OSD element = null;;
+ OSDArray array = new OSDArray();
+ int thisID = 0;
+ bool negativeID = false;
+
lock (queue)
{
if (queue.Count == 0)
return NoEvents(requestID, pAgentId);
- element = queue.Dequeue(); // 15s timeout
- }
-
- int thisID = 0;
- lock (m_ids)
- thisID = m_ids[pAgentId];
-
- OSDArray array = new OSDArray();
- if (element == null) // didn't have an event in 15s
- {
- // Send it a fake event to keep the client polling! It doesn't like 502s like the proxys say!
- array.Add(EventQueueHelper.KeepAliveEvent());
- //m_log.DebugFormat("[EVENTQUEUE]: adding fake event for {0} in region {1}", pAgentId, m_scene.RegionInfo.RegionName);
- }
- else
- {
- if (DebugLevel > 0)
- LogOutboundDebugMessage(element, pAgentId);
- array.Add(element);
+ lock (m_ids)
+ thisID = m_ids[pAgentId];
- lock (queue)
+ if (thisID < 0)
{
- while (queue.Count > 0)
- {
- element = queue.Dequeue();
+ negativeID = true;
+ thisID = -thisID;
+ }
+
+ while (queue.Count > 0)
+ {
+ element = queue.Dequeue();
+ // add elements until a marker is found
+ // so they get into a response
+ if (element == null)
+ break;
+ if (DebugLevel > 0)
+ LogOutboundDebugMessage(element, pAgentId);
+ array.Add(element);
+ thisID++;
+ }
+ }
- if (DebugLevel > 0)
- LogOutboundDebugMessage(element, pAgentId);
+ OSDMap events = null;
- array.Add(element);
- thisID++;
- }
- }
+ if (array.Count > 0)
+ {
+ events = new OSDMap();
+ events.Add("events", array);
+ events.Add("id", new OSDInteger(thisID));
}
- OSDMap events = new OSDMap();
- events.Add("events", array);
+ if (negativeID && element == null)
+ {
+ Random rnd = new Random(Environment.TickCount);
+ thisID = rnd.Next(30000000);
+ if (thisID < 0)
+ thisID = -thisID;
+ }
- events.Add("id", new OSDInteger(thisID));
lock (m_ids)
{
m_ids[pAgentId] = thisID + 1;
}
+
+ // if there where no elements before a marker send a NoEvents
+ if (array.Count == 0)
+ return NoEvents(requestID, pAgentId);
+
Hashtable responsedata = new Hashtable();
responsedata["int_response_code"] = 200;
responsedata["content_type"] = "application/xml";
@@ -432,7 +469,6 @@ namespace OpenSim.Region.ClientStack.Linden
responsedata["http_protocol_version"] = "HTTP/1.0";
return responsedata;
}
-
public void DisableSimulator(ulong handle, UUID avatarID)
{
--
cgit v1.1