mirror of
https://github.com/opensim/opensim.git
synced 2026-08-06 09:16:28 +08:00
* Adds the ability to have a thread efficient long poll service (such as the eventqueue)
* If this doesn't melt the Http Server, this will significantly reduce the number of threads in use on regions with many users. * Adds AddPollServiceHTTPHandler, and RemovePollServiceHTTPHandler to BaseHttpServer * Generic enough to be used for many long poll services, not only the EventQueue.
This commit is contained in:
@@ -61,7 +61,7 @@ namespace OpenSim.Region.CoreModules.Framework.EventQueue
|
||||
|
||||
private Dictionary<UUID, int> m_ids = new Dictionary<UUID, int>();
|
||||
|
||||
private Dictionary<UUID, BlockingLLSDQueue> queues = new Dictionary<UUID, BlockingLLSDQueue>();
|
||||
private Dictionary<UUID, Queue<OSD>> queues = new Dictionary<UUID, Queue<OSD>>();
|
||||
private Dictionary<UUID, UUID> m_QueueUUIDAvatarMapping = new Dictionary<UUID, UUID>();
|
||||
private Dictionary<UUID, UUID> m_AvatarQueueUUIDMapping = new Dictionary<UUID, UUID>();
|
||||
|
||||
@@ -131,7 +131,7 @@ namespace OpenSim.Region.CoreModules.Framework.EventQueue
|
||||
/// </summary>
|
||||
/// <param name="agentId"></param>
|
||||
/// <returns></returns>
|
||||
private BlockingLLSDQueue TryGetQueue(UUID agentId)
|
||||
private Queue<OSD> TryGetQueue(UUID agentId)
|
||||
{
|
||||
lock (queues)
|
||||
{
|
||||
@@ -141,7 +141,7 @@ namespace OpenSim.Region.CoreModules.Framework.EventQueue
|
||||
"[EVENTQUEUE]: Adding new queue for agent {0} in region {1}",
|
||||
agentId, m_scene.RegionInfo.RegionName);
|
||||
|
||||
queues[agentId] = new BlockingLLSDQueue();
|
||||
queues[agentId] = new Queue<OSD>();
|
||||
}
|
||||
|
||||
return queues[agentId];
|
||||
@@ -153,7 +153,7 @@ namespace OpenSim.Region.CoreModules.Framework.EventQueue
|
||||
/// </summary>
|
||||
/// <param name="agentId"></param>
|
||||
/// <returns></returns>
|
||||
private BlockingLLSDQueue GetQueue(UUID agentId)
|
||||
private Queue<OSD> GetQueue(UUID agentId)
|
||||
{
|
||||
lock (queues)
|
||||
{
|
||||
@@ -173,7 +173,7 @@ namespace OpenSim.Region.CoreModules.Framework.EventQueue
|
||||
//m_log.DebugFormat("[EVENTQUEUE]: Enqueuing event for {0} in region {1}", avatarID, m_scene.RegionInfo.RegionName);
|
||||
try
|
||||
{
|
||||
BlockingLLSDQueue queue = GetQueue(avatarID);
|
||||
Queue<OSD> queue = GetQueue(avatarID);
|
||||
if (queue != null)
|
||||
queue.Enqueue(ev);
|
||||
}
|
||||
@@ -203,7 +203,7 @@ namespace OpenSim.Region.CoreModules.Framework.EventQueue
|
||||
m_log.DebugFormat("[EVENTQUEUE]: Closed client {0} in region {1}", AgentID, m_scene.RegionInfo.RegionName);
|
||||
|
||||
int count = 0;
|
||||
while (queues.ContainsKey(AgentID) && queues[AgentID].Count() > 0 && count++ < 5)
|
||||
while (queues.ContainsKey(AgentID) && queues[AgentID].Count > 0 && count++ < 5)
|
||||
{
|
||||
Thread.Sleep(1000);
|
||||
}
|
||||
@@ -226,7 +226,7 @@ namespace OpenSim.Region.CoreModules.Framework.EventQueue
|
||||
foreach (UUID ky in removeitems)
|
||||
{
|
||||
m_AvatarQueueUUIDMapping.Remove(ky);
|
||||
MainServer.Instance.RemoveHTTPHandler("","/CAPS/EQG/" + ky.ToString() + "/");
|
||||
MainServer.Instance.RemovePollServiceHTTPHandler("","/CAPS/EQG/" + ky.ToString() + "/");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -315,8 +315,8 @@ namespace OpenSim.Region.CoreModules.Framework.EventQueue
|
||||
}));
|
||||
|
||||
// This will persist this beyond the expiry of the caps handlers
|
||||
MainServer.Instance.AddHTTPHandler(
|
||||
capsBase + EventQueueGetUUID.ToString() + "/", EventQueuePath2);
|
||||
MainServer.Instance.AddPollServiceHTTPHandler(
|
||||
capsBase + EventQueueGetUUID.ToString() + "/", EventQueuePath2, new PollServiceEventArgs(HasEvents, GetEvents, NoEvents, agentID));
|
||||
|
||||
Random rnd = new Random(Environment.TickCount);
|
||||
lock (m_ids)
|
||||
@@ -326,6 +326,73 @@ namespace OpenSim.Region.CoreModules.Framework.EventQueue
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasEvents(UUID agentID)
|
||||
{
|
||||
Queue<OSD> queue = TryGetQueue(agentID);
|
||||
if (queue.Count > 0)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
public Hashtable GetEvents(UUID pAgentId, string request)
|
||||
{
|
||||
Queue<OSD> queue = TryGetQueue(pAgentId);
|
||||
OSD 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
|
||||
{
|
||||
array.Add(element);
|
||||
while (queue.Count > 0)
|
||||
{
|
||||
array.Add(queue.Dequeue());
|
||||
thisID++;
|
||||
}
|
||||
}
|
||||
|
||||
OSDMap events = new OSDMap();
|
||||
events.Add("events", array);
|
||||
|
||||
events.Add("id", new OSDInteger(thisID));
|
||||
lock (m_ids)
|
||||
{
|
||||
m_ids[pAgentId] = thisID + 1;
|
||||
}
|
||||
Hashtable responsedata = new Hashtable();
|
||||
responsedata["int_response_code"] = 200;
|
||||
responsedata["content_type"] = "application/xml";
|
||||
responsedata["keepalive"] = false;
|
||||
responsedata["str_response_string"] = OSDParser.SerializeLLSDXmlString(events);
|
||||
return responsedata;
|
||||
//m_log.DebugFormat("[EVENTQUEUE]: sending response for {0} in region {1}: {2}", agentID, m_scene.RegionInfo.RegionName, responsedata["str_response_string"]);
|
||||
}
|
||||
|
||||
public Hashtable NoEvents()
|
||||
{
|
||||
Hashtable responsedata = new Hashtable();
|
||||
responsedata["int_response_code"] = 502;
|
||||
responsedata["content_type"] = "text/plain";
|
||||
responsedata["keepalive"] = false;
|
||||
responsedata["str_response_string"] = "Upstream error: ";
|
||||
responsedata["error_status_text"] = "Upstream error:";
|
||||
responsedata["http_protocol_version"] = "HTTP/1.0";
|
||||
return responsedata;
|
||||
}
|
||||
|
||||
public Hashtable ProcessQueue(Hashtable request, UUID agentID, Caps caps)
|
||||
{
|
||||
// TODO: this has to be redone to not busy-wait (and block the thread),
|
||||
@@ -341,8 +408,8 @@ namespace OpenSim.Region.CoreModules.Framework.EventQueue
|
||||
// m_log.DebugFormat(debug + " ]", agentID, m_scene.RegionInfo.RegionName, System.Threading.Thread.CurrentThread.Name);
|
||||
// }
|
||||
|
||||
BlockingLLSDQueue queue = TryGetQueue(agentID);
|
||||
OSD element = queue.Dequeue(15000); // 15s timeout
|
||||
Queue<OSD> queue = TryGetQueue(agentID);
|
||||
OSD element = queue.Dequeue(); // 15s timeout
|
||||
|
||||
Hashtable responsedata = new Hashtable();
|
||||
|
||||
@@ -381,9 +448,9 @@ namespace OpenSim.Region.CoreModules.Framework.EventQueue
|
||||
else
|
||||
{
|
||||
array.Add(element);
|
||||
while (queue.Count() > 0)
|
||||
while (queue.Count > 0)
|
||||
{
|
||||
array.Add(queue.Dequeue(1));
|
||||
array.Add(queue.Dequeue());
|
||||
thisID++;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user