From 032aeb8b5d05f5f5a8ef8c6e0fe572a321717c35 Mon Sep 17 00:00:00 2001 From: Teravus Ovares Date: Wed, 29 Jul 2009 02:15:45 +0000 Subject: * 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. --- .../Framework/Servers/HttpServer/BaseHttpServer.cs | 95 +++++++++++++- .../Servers/HttpServer/Interfaces/IHttpServer.cs | 5 + .../Servers/HttpServer/PollServiceEventArgs.cs | 53 ++++++++ .../Servers/HttpServer/PollServiceHttpRequest.cs | 48 +++++++ .../HttpServer/PollServiceRequestManager.cs | 145 +++++++++++++++++++++ .../Servers/HttpServer/PollServiceWorkerThread.cs | 100 ++++++++++++++ OpenSim/Framework/Servers/Tests/OSHttpTests.cs | 1 + .../Framework/EventQueue/EventQueueGetModule.cs | 93 +++++++++++-- bin/HttpServer_OpenSim.dll | Bin 123904 -> 113152 bytes bin/HttpServer_OpenSim.pdb | Bin 341504 -> 302592 bytes bin/HttpServer_OpenSim.xml | 5 + 11 files changed, 527 insertions(+), 18 deletions(-) create mode 100644 OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs create mode 100644 OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs create mode 100644 OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs create mode 100644 OpenSim/Framework/Servers/HttpServer/PollServiceWorkerThread.cs diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs index 4532e76..369d7d4 100644 --- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs +++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs @@ -64,6 +64,9 @@ namespace OpenSim.Framework.Servers.HttpServer protected Dictionary m_HTTPHandlers = new Dictionary(); protected Dictionary m_agentHandlers = new Dictionary(); + protected Dictionary m_pollHandlers = + new Dictionary(); + protected uint m_port; protected uint m_sslport; protected bool m_ssl; @@ -72,6 +75,8 @@ namespace OpenSim.Framework.Servers.HttpServer protected IPAddress m_listenIPAddress = IPAddress.Any; + private PollServiceRequestManager m_PollServiceManager; + public uint SSLPort { get { return m_sslport; } @@ -189,6 +194,26 @@ namespace OpenSim.Framework.Servers.HttpServer return false; } + public bool AddPollServiceHTTPHandler(string methodName, GenericHTTPMethod handler, PollServiceEventArgs args) + { + bool pollHandlerResult = false; + lock (m_pollHandlers) + { + if (!m_pollHandlers.ContainsKey( methodName)) + { + m_pollHandlers.Add(methodName,args); + pollHandlerResult = true; + + } + } + + if (pollHandlerResult) + return AddHTTPHandler(methodName, handler); + + return false; + + } + // Note that the agent string is provided simply to differentiate // the handlers - it is NOT required to be an actual agent header // value. @@ -230,8 +255,19 @@ namespace OpenSim.Framework.Servers.HttpServer { IHttpClientContext context = (IHttpClientContext)source; IHttpRequest request = args.Request; + - OnHandleRequestIOThread(context,request); + PollServiceEventArgs psEvArgs; + if (TryGetPollServiceHTTPHandler(request.UriPath.ToString(), out psEvArgs)) + { + + m_PollServiceManager.Enqueue(new PollServiceHttpRequest(psEvArgs, context, request)); + //DoHTTPGruntWork(psEvArgs.NoEvents(),new OSHttpResponse(new HttpResponse(context, request))); + } + else + { + OnHandleRequestIOThread(context, request); + } } @@ -341,7 +377,7 @@ namespace OpenSim.Framework.Servers.HttpServer string requestBody = reader.ReadToEnd(); reader.Close(); - requestStream.Close(); + //requestStream.Close(); Hashtable keysvals = new Hashtable(); Hashtable headervals = new Hashtable(); @@ -527,6 +563,36 @@ namespace OpenSim.Framework.Servers.HttpServer } } + private bool TryGetPollServiceHTTPHandler(string handlerKey, out PollServiceEventArgs oServiceEventArgs) + { + string bestMatch = null; + + lock (m_pollHandlers) + { + foreach (string pattern in m_pollHandlers.Keys) + { + if (handlerKey.StartsWith(pattern)) + { + if (String.IsNullOrEmpty(bestMatch) || pattern.Length > bestMatch.Length) + { + bestMatch = pattern; + } + } + } + + if (String.IsNullOrEmpty(bestMatch)) + { + oServiceEventArgs = null; + return false; + } + else + { + oServiceEventArgs = m_pollHandlers[bestMatch]; + return true; + } + } + } + private bool TryGetHTTPHandler(string handlerKey, out GenericHTTPMethod HTTPHandler) { //m_log.DebugFormat("[BASE HTTP HANDLER]: Looking for HTTP handler for {0}", handlerKey); @@ -822,7 +888,7 @@ namespace OpenSim.Framework.Servers.HttpServer { response.Send(); response.OutputStream.Flush(); - response.OutputStream.Close(); + //response.OutputStream.Close(); } catch (IOException e) { @@ -1237,7 +1303,7 @@ namespace OpenSim.Framework.Servers.HttpServer } } - private static void DoHTTPGruntWork(Hashtable responsedata, OSHttpResponse response) + internal void DoHTTPGruntWork(Hashtable responsedata, OSHttpResponse response) { //m_log.Info("[BASE HTTP SERVER]: Doing HTTP Grunt work with response"); int responsecode = (int)responsedata["int_response_code"]; @@ -1261,7 +1327,7 @@ namespace OpenSim.Framework.Servers.HttpServer } //Even though only one other part of the entire code uses HTTPHandlers, we shouldn't expect this //and should check for NullReferenceExceptions - + if (string.IsNullOrEmpty(contentType)) { contentType = "text/html"; @@ -1402,6 +1468,8 @@ namespace OpenSim.Framework.Servers.HttpServer //m_workerThread.Start(); //ThreadTracker.Add(m_workerThread); StartHTTP(); + + } private void StartHTTP() @@ -1434,6 +1502,9 @@ namespace OpenSim.Framework.Servers.HttpServer m_httpListener2.RequestReceived += OnRequest; //m_httpListener.Start(); m_httpListener2.Start(64); + + // Long Poll Service Manager with 3 worker threads a 25 second timeout for no events + m_PollServiceManager = new PollServiceRequestManager(this, 3, 25000); HTTPDRunning = true; //HttpListenerContext context; @@ -1514,6 +1585,20 @@ namespace OpenSim.Framework.Servers.HttpServer } } + public void RemovePollServiceHTTPHandler(string httpMethod, string path) + { + lock (m_pollHandlers) + { + if (m_pollHandlers.ContainsKey(httpMethod)) + { + m_pollHandlers.Remove(httpMethod); + } + } + + RemoveHTTPHandler(httpMethod, path); + + } + public bool RemoveAgentHandler(string agent, IHttpAgentHandler handler) { try diff --git a/OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpServer.cs index c415dfb..9095831 100644 --- a/OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpServer.cs +++ b/OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpServer.cs @@ -74,6 +74,9 @@ namespace OpenSim.Framework.Servers.HttpServer /// bool AddHTTPHandler(string methodName, GenericHTTPMethod handler); + + bool AddPollServiceHTTPHandler(string methodName, GenericHTTPMethod handler, PollServiceEventArgs args); + /// /// Adds a LLSD handler, yay. /// @@ -114,6 +117,8 @@ namespace OpenSim.Framework.Servers.HttpServer /// /// void RemoveHTTPHandler(string httpMethod, string path); + + void RemovePollServiceHTTPHandler(string httpMethod, string path); bool RemoveLLSDHandler(string path, LLSDMethod handler); diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs new file mode 100644 index 0000000..fed490e --- /dev/null +++ b/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs @@ -0,0 +1,53 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using OpenMetaverse; +namespace OpenSim.Framework.Servers.HttpServer +{ + public delegate bool HasEventsMethod(UUID pId); + + public delegate Hashtable GetEventsMethod(UUID pId, string request); + + public delegate Hashtable NoEventsMethod(); + + public class PollServiceEventArgs : EventArgs + { + public HasEventsMethod HasEvents; + public GetEventsMethod GetEvents; + public NoEventsMethod NoEvents; + public UUID Id; + public PollServiceEventArgs(HasEventsMethod pHasEvents, GetEventsMethod pGetEvents, NoEventsMethod pNoEvents,UUID pId) + { + HasEvents = pHasEvents; + GetEvents = pGetEvents; + NoEvents = pNoEvents; + Id = pId; + } + } +} diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs new file mode 100644 index 0000000..ff7c1e8 --- /dev/null +++ b/OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs @@ -0,0 +1,48 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using HttpServer; + +namespace OpenSim.Framework.Servers.HttpServer +{ + + public class PollServiceHttpRequest + { + public readonly PollServiceEventArgs PollServiceArgs; + public readonly IHttpClientContext HttpContext; + public readonly IHttpRequest Request; + public readonly int RequestTime; + public PollServiceHttpRequest(PollServiceEventArgs pPollServiceArgs, IHttpClientContext pHttpContext, IHttpRequest pRequest) + { + PollServiceArgs = pPollServiceArgs; + HttpContext = pHttpContext; + Request = pRequest; + RequestTime = System.Environment.TickCount; + } + } +} diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs new file mode 100644 index 0000000..7f632cf --- /dev/null +++ b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs @@ -0,0 +1,145 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Threading; +using HttpServer; + +namespace OpenSim.Framework.Servers.HttpServer +{ + public class PollServiceRequestManager + { + private readonly BaseHttpServer m_server; + private static Queue m_requests = Queue.Synchronized(new Queue()); + private uint m_WorkerThreadCount = 0; + private Thread[] m_workerThreads; + private PollServiceWorkerThread[] m_PollServiceWorkerThreads; + private Thread m_watcherThread; + private bool m_running = true; + + + + public PollServiceRequestManager(BaseHttpServer pSrv, uint pWorkerThreadCount, int pTimeout) + { + m_server = pSrv; + m_WorkerThreadCount = pWorkerThreadCount; + m_workerThreads = new Thread[m_WorkerThreadCount]; + m_PollServiceWorkerThreads = new PollServiceWorkerThread[m_WorkerThreadCount]; + m_watcherThread = new Thread(ThreadStart); + + + //startup worker threads + for (uint i=0;i 0; tc++) + { + //Loop over number of requests each thread handles. + for (int i=0;i 0;i++) + { + try + { + m_PollServiceWorkerThreads[tc].Enqueue((PollServiceHttpRequest)m_requests.Dequeue()); + } + catch (InvalidOperationException) + { + // The queue is empty, we did our calculations wrong! + return; + } + + } + } + } + + } + + + + ~PollServiceRequestManager() + { + foreach (object o in m_requests) + { + PollServiceHttpRequest req = (PollServiceHttpRequest) o; + m_server.DoHTTPGruntWork(req.PollServiceArgs.NoEvents(), new OSHttpResponse(new HttpResponse(req.HttpContext, req.Request))); + } + + m_requests.Clear(); + + foreach (Thread t in m_workerThreads) + { + t.Abort(); + } + m_running = false; + } + } +} diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceWorkerThread.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceWorkerThread.cs new file mode 100644 index 0000000..4c0be78 --- /dev/null +++ b/OpenSim/Framework/Servers/HttpServer/PollServiceWorkerThread.cs @@ -0,0 +1,100 @@ +using System; +using System.Collections; +using System.Collections.Generic; +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System.IO; +using System.Text; +using HttpServer; +using OpenMetaverse; + +namespace OpenSim.Framework.Servers.HttpServer +{ + public delegate void ReQueuePollServiceItem(PollServiceHttpRequest req); + + public class PollServiceWorkerThread + { + public event ReQueuePollServiceItem ReQueue; + + private readonly BaseHttpServer m_server; + private BlockingQueue m_request; + private bool m_running = true; + private int m_timeout = 25000; + + + + public PollServiceWorkerThread(BaseHttpServer pSrv, int pTimeout) + { + m_request = new BlockingQueue(); + m_server = pSrv; + m_timeout = pTimeout; + } + + public void ThreadStart(object o) + { + Run(); + } + + public void Run() + { + while (m_running) + { + PollServiceHttpRequest req = m_request.Dequeue(); + if (req.PollServiceArgs.HasEvents(req.PollServiceArgs.Id)) + { + StreamReader str = new StreamReader(req.Request.Body); + + Hashtable responsedata = req.PollServiceArgs.GetEvents(req.PollServiceArgs.Id, str.ReadToEnd()); + m_server.DoHTTPGruntWork(responsedata, + new OSHttpResponse(new HttpResponse(req.HttpContext, req.Request))); + } + else + { + if ((Environment.TickCount - req.RequestTime) > m_timeout) + { + m_server.DoHTTPGruntWork(req.PollServiceArgs.NoEvents(), + new OSHttpResponse(new HttpResponse(req.HttpContext, req.Request))); + } + else + { + ReQueuePollServiceItem reQueueItem = ReQueue; + if (reQueueItem != null) + reQueueItem(req); + } + } + } + + + } + + internal void Enqueue(PollServiceHttpRequest pPollServiceHttpRequest) + { + m_request.Enqueue(pPollServiceHttpRequest); + } + } +} diff --git a/OpenSim/Framework/Servers/Tests/OSHttpTests.cs b/OpenSim/Framework/Servers/Tests/OSHttpTests.cs index f7f0afa..a6a90dc 100644 --- a/OpenSim/Framework/Servers/Tests/OSHttpTests.cs +++ b/OpenSim/Framework/Servers/Tests/OSHttpTests.cs @@ -67,6 +67,7 @@ namespace OpenSim.Framework.Servers.Tests public void Send(byte[] buffer) {} public void Send(byte[] buffer, int offset, int size) {} public void Respond(string httpVersion, HttpStatusCode statusCode, string reason, string body, string contentType) {} + public void Close() { } public event EventHandler Disconnected = delegate { }; /// diff --git a/OpenSim/Region/CoreModules/Framework/EventQueue/EventQueueGetModule.cs b/OpenSim/Region/CoreModules/Framework/EventQueue/EventQueueGetModule.cs index 81ea267..81b47be 100644 --- a/OpenSim/Region/CoreModules/Framework/EventQueue/EventQueueGetModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EventQueue/EventQueueGetModule.cs @@ -61,7 +61,7 @@ namespace OpenSim.Region.CoreModules.Framework.EventQueue private Dictionary m_ids = new Dictionary(); - private Dictionary queues = new Dictionary(); + private Dictionary> queues = new Dictionary>(); private Dictionary m_QueueUUIDAvatarMapping = new Dictionary(); private Dictionary m_AvatarQueueUUIDMapping = new Dictionary(); @@ -131,7 +131,7 @@ namespace OpenSim.Region.CoreModules.Framework.EventQueue /// /// /// - private BlockingLLSDQueue TryGetQueue(UUID agentId) + private Queue 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(); } return queues[agentId]; @@ -153,7 +153,7 @@ namespace OpenSim.Region.CoreModules.Framework.EventQueue /// /// /// - private BlockingLLSDQueue GetQueue(UUID agentId) + private Queue 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 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 queue = TryGetQueue(agentID); + if (queue.Count > 0) + return true; + else + return false; + + } + + public Hashtable GetEvents(UUID pAgentId, string request) + { + Queue 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 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++; } } diff --git a/bin/HttpServer_OpenSim.dll b/bin/HttpServer_OpenSim.dll index 77042a0..4775ec0 100644 Binary files a/bin/HttpServer_OpenSim.dll and b/bin/HttpServer_OpenSim.dll differ diff --git a/bin/HttpServer_OpenSim.pdb b/bin/HttpServer_OpenSim.pdb index e3abbe2..b885eda 100644 Binary files a/bin/HttpServer_OpenSim.pdb and b/bin/HttpServer_OpenSim.pdb differ diff --git a/bin/HttpServer_OpenSim.xml b/bin/HttpServer_OpenSim.xml index 22cc1c0..c549ebc 100644 --- a/bin/HttpServer_OpenSim.xml +++ b/bin/HttpServer_OpenSim.xml @@ -2339,6 +2339,11 @@ + + + Closes the streams and disposes of the unmanaged resources + + Using SSL or other encryption method. -- cgit v1.1