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> /// <summary>
/// May return a null queue /// May return a null queue
/// </summary> /// </summary>
@ -278,47 +257,95 @@ namespace OpenSim.Region.ClientStack.Linden
public void OnRegisterCaps(UUID agentID, Caps caps) public void OnRegisterCaps(UUID agentID, Caps caps)
{ {
// Register an event queue for the client // Register an event queue for the client
m_log.DebugFormat( m_log.DebugFormat(
"[EVENTQUEUE]: OnRegisterCaps: agentID {0} caps {1} region {2}", "[EVENTQUEUE]: OnRegisterCaps: agentID {0} caps {1} region {2}",
agentID, caps, m_scene.RegionInfo.RegionName); agentID, caps, m_scene.RegionInfo.RegionName);
// Let's instantiate a Queue for this agent right now
TryGetQueue(agentID);
UUID eventQueueGetUUID; 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! if (queues.ContainsKey(agentID))
// Its reuse caps path not queues those are been reused already queue = queues[agentID];
if (m_AvatarQueueUUIDMapping.ContainsKey(agentID)) else
queue = null;
if (queue == null)
{ {
m_log.DebugFormat("[EVENTQUEUE]: Found Existing UUID!"); queue = new Queue<OSD>();
eventQueueGetUUID = m_AvatarQueueUUIDMapping[agentID]; 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 else
{ {
eventQueueGetUUID = UUID.Random(); // push markers to handle old responses still waiting
m_AvatarQueueUUIDMapping.Add(agentID, eventQueueGetUUID); // this will cost at most viewer getting two forced noevents
m_log.DebugFormat("[EVENTQUEUE]: Using random UUID!"); // 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( caps.RegisterPollHandler(
"EventQueueGet", "EventQueueGet",
new PollServiceEventArgs(null, GenerateEqgCapPath(eventQueueGetUUID), HasEvents, GetEvents, NoEvents, agentID, SERVER_EQ_TIME_NO_EVENTS)); 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) public bool HasEvents(UUID requestID, UUID agentID)
@ -361,55 +388,65 @@ namespace OpenSim.Region.ClientStack.Linden
return NoEvents(requestID, pAgentId); return NoEvents(requestID, pAgentId);
} }
OSD element; OSD element = null;;
OSDArray array = new OSDArray();
int thisID = 0;
bool negativeID = false;
lock (queue) lock (queue)
{ {
if (queue.Count == 0) if (queue.Count == 0)
return NoEvents(requestID, pAgentId); return NoEvents(requestID, pAgentId);
element = queue.Dequeue(); // 15s timeout
}
int thisID = 0; lock (m_ids)
lock (m_ids) thisID = m_ids[pAgentId];
thisID = m_ids[pAgentId];
OSDArray array = new OSDArray(); if (thisID < 0)
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)
{ {
while (queue.Count > 0) negativeID = true;
{ thisID = -thisID;
element = queue.Dequeue(); }
if (DebugLevel > 0) while (queue.Count > 0)
LogOutboundDebugMessage(element, pAgentId); {
element = queue.Dequeue();
array.Add(element); // add elements until a marker is found
thisID++; // so they get into a response
} if (element == null)
break;
if (DebugLevel > 0)
LogOutboundDebugMessage(element, pAgentId);
array.Add(element);
thisID++;
} }
} }
OSDMap events = new OSDMap(); OSDMap events = null;
events.Add("events", array);
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) lock (m_ids)
{ {
m_ids[pAgentId] = thisID + 1; 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(); Hashtable responsedata = new Hashtable();
responsedata["int_response_code"] = 200; responsedata["int_response_code"] = 200;
responsedata["content_type"] = "application/xml"; responsedata["content_type"] = "application/xml";
@ -433,7 +470,6 @@ namespace OpenSim.Region.ClientStack.Linden
return responsedata; return responsedata;
} }
public void DisableSimulator(ulong handle, UUID avatarID) public void DisableSimulator(ulong handle, UUID avatarID)
{ {
OSD item = EventQueueHelper.DisableSimulator(handle); OSD item = EventQueueHelper.DisableSimulator(handle);