add queue transition code needs review/more testing

avinationmerge
UbitUmarov 2014-07-25 17:29:41 +01:00
parent fa59cddc28
commit 70890e211a
1 changed files with 116 additions and 80 deletions

View File

@ -175,27 +175,6 @@ namespace OpenSim.Region.ClientStack.Linden
}
}
/// <summary>
/// Always returns a valid queue
/// </summary>
/// <param name="agentId"></param>
/// <returns></returns>
private Queue<OSD> 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<OSD>();
}
return queues[agentId];
}
}
/// <summary>
/// May return a null queue
/// </summary>
@ -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<OSD> 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<OSD>();
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];
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 (queue)
if (thisID < 0)
{
while (queue.Count > 0)
{
element = queue.Dequeue();
if (DebugLevel > 0)
LogOutboundDebugMessage(element, pAgentId);
array.Add(element);
thisID++;
}
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++;
}
}
OSDMap events = new OSDMap();
events.Add("events", array);
OSDMap events = null;
if (array.Count > 0)
{
events = new OSDMap();
events.Add("events", array);
events.Add("id", new OSDInteger(thisID));
}
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)
{