From b379e790a279a0ed70d2c889c12ecb6849765e02 Mon Sep 17 00:00:00 2001 From: Melanie Date: Fri, 7 Sep 2012 23:27:40 +0200 Subject: [PATCH 1/5] Set the maximum number of concurrent connections to a service endpoint to 50. This doesn't work on stock mono but it works in Avination and also under Windoze. --- OpenSim/Region/Application/Application.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/OpenSim/Region/Application/Application.cs b/OpenSim/Region/Application/Application.cs index ebfebc4443..0dbb95a89d 100644 --- a/OpenSim/Region/Application/Application.cs +++ b/OpenSim/Region/Application/Application.cs @@ -27,6 +27,7 @@ using System; using System.IO; +using System.Net; using System.Reflection; using log4net; using log4net.Config; @@ -73,6 +74,7 @@ namespace OpenSim AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException); + ServicePointManager.DefaultConnectionLimit = 50; // Add the arguments supplied when running the application to the configuration ArgvConfigSource configSource = new ArgvConfigSource(args); From 0556bbefdda9643abf4bbba08ab8e3f066501b74 Mon Sep 17 00:00:00 2001 From: Melanie Date: Sun, 9 Sep 2012 16:30:01 +0200 Subject: [PATCH 2/5] Catch zero UUIDs in LSL and shout as an error. Also catch attempts to send IM to UUID.Zero because it ties up XMLRPC handlers needlessly. --- .../CoreModules/Avatar/InstantMessage/MessageTransferModule.cs | 3 +++ .../Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs index 1406aaec25..0c067d7c61 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs @@ -137,6 +137,9 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage { UUID toAgentID = new UUID(im.toAgentID); + if (toAgentID == UUID.Zero) + return; + // Try root avatar only first foreach (Scene scene in m_Scenes) { diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index d5e611c5e4..f9b4bfd475 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -3420,7 +3420,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llInstantMessage(string user, string message) { UUID result; - if (!UUID.TryParse(user, out result)) + if (!UUID.TryParse(user, out result) || result == UUID.Zero) { ShoutError("An invalid key was passed to llInstantMessage"); ScriptSleep(2000); From afb4e06f63dd6a532c85b71f0d6c486ae38815fe Mon Sep 17 00:00:00 2001 From: Melanie Date: Sun, 9 Sep 2012 17:41:10 +0200 Subject: [PATCH 3/5] Reduce max concurrent endpoint connections from 50 to 6 (was 2 before) --- OpenSim/Region/Application/Application.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/Application/Application.cs b/OpenSim/Region/Application/Application.cs index 0dbb95a89d..78636c46e6 100644 --- a/OpenSim/Region/Application/Application.cs +++ b/OpenSim/Region/Application/Application.cs @@ -74,7 +74,7 @@ namespace OpenSim AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException); - ServicePointManager.DefaultConnectionLimit = 50; + ServicePointManager.DefaultConnectionLimit = 6; // Add the arguments supplied when running the application to the configuration ArgvConfigSource configSource = new ArgvConfigSource(args); From 657428a43906c5e65ad56ed96fa05d82f84d6c9b Mon Sep 17 00:00:00 2001 From: Melanie Date: Mon, 10 Sep 2012 01:52:02 +0200 Subject: [PATCH 4/5] Remove commented code --- .../ClientStack/Linden/Caps/WebFetchInvDescModule.cs | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs index 2475b1f18e..e996fe8df2 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs @@ -60,7 +60,6 @@ namespace OpenSim.Region.ClientStack.Linden private WebFetchInvDescHandler m_webFetchHandler; -// private ManualResetEvent m_ev = new ManualResetEvent(true); private object m_lock = new object(); private Dictionary m_capsDict = new Dictionary(); @@ -162,14 +161,6 @@ namespace OpenSim.Region.ClientStack.Linden { lock (m_lock) { -/* - if (m_ev.WaitOne(0)) - { - m_ev.Reset(); - return true; - } - return false; - */ return !m_busy; } } @@ -215,7 +206,6 @@ namespace OpenSim.Region.ClientStack.Linden if (!m_requests.TryGetValue(requestID, out requestHash)) { m_busy = false; - // m_ev.Set(); response["str_response_string"] = "Invalid request"; return response; } @@ -233,7 +223,6 @@ namespace OpenSim.Region.ClientStack.Linden finally { lock (m_lock) -// m_ev.Set(); m_busy = false; } From a6753c14a509e11f65829b87070b440ac3b87c4a Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 11 Sep 2012 10:39:43 +0200 Subject: [PATCH 5/5] Revamp the v3 inventory sending. Uses threads and some nifty mechanics to leverage the Poll Service without blocking it's workers. --- .../Linden/Caps/WebFetchInvDescModule.cs | 200 +++++++++++------- prebuild.xml | 1 + 2 files changed, 119 insertions(+), 82 deletions(-) diff --git a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs index e996fe8df2..4908c2c7e1 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs @@ -42,6 +42,7 @@ using OpenSim.Region.Framework.Scenes; using OpenSim.Services.Interfaces; using Caps = OpenSim.Framework.Capabilities.Caps; using OpenSim.Capabilities.Handlers; +using OpenSim.Framework.Monitoring; namespace OpenSim.Region.ClientStack.Linden { @@ -58,13 +59,13 @@ namespace OpenSim.Region.ClientStack.Linden private IInventoryService m_InventoryService; private ILibraryService m_LibraryService; - private WebFetchInvDescHandler m_webFetchHandler; - - private object m_lock = new object(); + private static WebFetchInvDescHandler m_webFetchHandler; private Dictionary m_capsDict = new Dictionary(); - private Dictionary m_requests = new Dictionary(); - bool m_busy = false; + private static Thread[] m_workerThreads = null; + + private static OpenMetaverse.BlockingQueue m_queue = + new OpenMetaverse.BlockingQueue(); #region ISharedRegionModule Members @@ -94,6 +95,22 @@ namespace OpenSim.Region.ClientStack.Linden m_scene.EventManager.OnRegisterCaps += RegisterCaps; m_scene.EventManager.OnDeregisterCaps += DeregisterCaps; + + if (m_workerThreads == null) + { + m_workerThreads = new Thread[2]; + + for (uint i = 0; i < 2; i++) + { + m_workerThreads[i] = Watchdog.StartThread(DoInventoryRequests, + String.Format("InventoryWorkerThread{0}", i), + ThreadPriority.Normal, + false, + true, + null, + int.MaxValue); + } + } } public void PostInitialise() @@ -111,13 +128,103 @@ namespace OpenSim.Region.ClientStack.Linden #endregion + ~WebFetchInvDescModule() + { + foreach (Thread t in m_workerThreads) + t.Abort(); + } + + private class PollServiceInventoryEventArgs : PollServiceEventArgs + { + private List requests = + new List(); + private Dictionary responses = + new Dictionary(); + + public PollServiceInventoryEventArgs(UUID pId) : + base(null, null, null, null, pId, 30000) + { + HasEvents = (x, y) => { return this.responses.ContainsKey(x); }; + GetEvents = (x, y, s) => + { + try + { + return this.responses[x]; + } + finally + { + responses.Remove(x); + } + }; + + Request = (x, y) => + { + y["RequestID"] = x.ToString(); + lock (this.requests) + this.requests.Add(y); + + m_queue.Enqueue(this); + }; + + NoEvents = (x, y) => + { + lock (this.requests) + { + Hashtable request = requests.Find(id => id["RequestID"].ToString() == x.ToString()); + requests.Remove(request); + } + + Hashtable response = new Hashtable(); + + response["int_response_code"] = 500; + response["str_response_string"] = "Script timeout"; + response["content_type"] = "text/plain"; + response["keepalive"] = false; + response["reusecontext"] = false; + + return response; + }; + } + + public void Process() + { + Hashtable request = null; + + try + { + lock (this.requests) + { + request = requests[0]; + requests.RemoveAt(0); + } + } + catch + { + return; + } + + UUID requestID = new UUID(request["RequestID"].ToString()); + + Hashtable response = new Hashtable(); + + response["int_response_code"] = 200; + response["content_type"] = "text/plain"; + response["keepalive"] = false; + response["reusecontext"] = false; + + response["str_response_string"] = m_webFetchHandler.FetchInventoryDescendentsRequest(request["body"].ToString(), String.Empty, String.Empty, null, null); + + responses[requestID] = response; + } + } + private void RegisterCaps(UUID agentID, Caps caps) { string capUrl = "/CAPS/" + UUID.Random() + "/"; // Register this as a poll service // absurd large timeout to tune later to make a bit less than viewer - PollServiceEventArgs args = new PollServiceEventArgs(HttpRequestHandler, HasEvents, GetEvents, NoEvents, agentID, 300000); + PollServiceInventoryEventArgs args = new PollServiceInventoryEventArgs(agentID); args.Type = PollServiceEventArgs.EventType.Inventory; MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args); @@ -135,8 +242,6 @@ namespace OpenSim.Region.ClientStack.Linden caps.RegisterHandler("FetchInventoryDescendents2", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl)); m_capsDict[agentID] = capUrl; - - m_busy = false; } private void DeregisterCaps(UUID agentID, Caps caps) @@ -150,83 +255,14 @@ namespace OpenSim.Region.ClientStack.Linden } } - public void HttpRequestHandler(UUID requestID, Hashtable request) + private void DoInventoryRequests() { -// m_log.DebugFormat("[FETCH2]: Received request {0}", requestID); - lock(m_lock) - m_requests[requestID] = request; - } - - private bool HasEvents(UUID requestID, UUID sessionID) - { - lock (m_lock) + while (true) { - return !m_busy; + PollServiceInventoryEventArgs args = m_queue.Dequeue(); + + args.Process(); } } - - private Hashtable NoEvents(UUID requestID, UUID sessionID) - { - lock(m_lock) - m_requests.Remove(requestID); - - Hashtable response = new Hashtable(); - - response["int_response_code"] = 500; - response["str_response_string"] = "Script timeout"; - response["content_type"] = "text/plain"; - response["keepalive"] = false; - response["reusecontext"] = false; - - lock (m_lock) - m_busy = false; - - return response; - } - - private Hashtable GetEvents(UUID requestID, UUID sessionID, string request) - { - lock (m_lock) - m_busy = true; - - Hashtable response = new Hashtable(); - - response["int_response_code"] = 500; - response["str_response_string"] = "Internal error"; - response["content_type"] = "text/plain"; - response["keepalive"] = false; - response["reusecontext"] = false; - - try - { - - Hashtable requestHash; - lock (m_lock) - { - if (!m_requests.TryGetValue(requestID, out requestHash)) - { - m_busy = false; - response["str_response_string"] = "Invalid request"; - return response; - } - m_requests.Remove(requestID); - } - -// m_log.DebugFormat("[FETCH2]: Processed request {0}", requestID); - - string reply = m_webFetchHandler.FetchInventoryDescendentsRequest(requestHash["body"].ToString(), String.Empty, String.Empty, null, null); - - - response["int_response_code"] = 200; - response["str_response_string"] = reply; - } - finally - { - lock (m_lock) - m_busy = false; - } - - return response; - } } } diff --git a/prebuild.xml b/prebuild.xml index 09336b3594..667efb5f02 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -1706,6 +1706,7 @@ +