From 5139db2638fcee945961ea8d5635def581b54a4d Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 12 Sep 2012 12:56:59 +0200 Subject: Add a timer to time out upload caps handlers that are not used. --- .../ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'OpenSim/Region/ClientStack') diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs index 9982556..c4a9a19 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs @@ -26,6 +26,7 @@ */ using System; +using System.Timers; using System.Collections; using System.Collections.Generic; using System.IO; @@ -1106,6 +1107,7 @@ namespace OpenSim.Region.ClientStack.Linden private string m_invType = String.Empty; private string m_assetType = String.Empty; + private Timer m_timeoutTimer = new Timer(); public AssetUploader(string assetName, string description, UUID assetID, UUID inventoryItem, UUID parentFolderID, string invType, string assetType, string path, @@ -1121,6 +1123,11 @@ namespace OpenSim.Region.ClientStack.Linden m_assetType = assetType; m_invType = invType; m_dumpAssetsToFile = dumpAssetsToFile; + + m_timeoutTimer.Elapsed += TimedOut; + m_timeoutTimer.Interval = 120000; + m_timeoutTimer.AutoReset = false; + m_timeoutTimer.Start(); } /// @@ -1163,6 +1170,11 @@ namespace OpenSim.Region.ClientStack.Linden return res; } + private void TimedOut(object sender, ElapsedEventArgs args) + { + httpListener.RemoveStreamHandler("POST", uploaderPath); + } + ///Left this in and commented in case there are unforseen issues //private void SaveAssetToFile(string filename, byte[] data) //{ -- cgit v1.1 From d8e9188908bd1f6ab505e5424f02071b44f0fab1 Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 12 Sep 2012 21:14:55 +0200 Subject: Stop expiry timer when upload is complete. Log if timeout is reached. --- OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'OpenSim/Region/ClientStack') diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs index c4a9a19..116055a 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs @@ -1149,6 +1149,7 @@ namespace OpenSim.Region.ClientStack.Linden res = LLSDHelpers.SerialiseLLSDReply(uploadComplete); httpListener.RemoveStreamHandler("POST", uploaderPath); + m_timeoutTimer.Stop(); // TODO: probably make this a better set of extensions here string extension = ".jp2"; @@ -1172,6 +1173,7 @@ namespace OpenSim.Region.ClientStack.Linden private void TimedOut(object sender, ElapsedEventArgs args) { + m_log.InfoFormat("[CAPS]: Removing URL and handler for timed out mesh upload"); httpListener.RemoveStreamHandler("POST", uploaderPath); } -- cgit v1.1 From e7932682a2405dab69cb6b4447dde952c2a5c080 Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 12 Sep 2012 21:24:09 +0200 Subject: Add a logger so the prior commit will work --- OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs | 3 +++ 1 file changed, 3 insertions(+) (limited to 'OpenSim/Region/ClientStack') diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs index 116055a..88957ff 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs @@ -1093,6 +1093,9 @@ namespace OpenSim.Region.ClientStack.Linden public class AssetUploader { + private static readonly ILog m_log = + LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + public event UpLoadedAsset OnUpLoad; private UpLoadedAsset handlerUpLoad = null; -- cgit v1.1 From 45fe25de0d9636690114091565775d264a0ca96f Mon Sep 17 00:00:00 2001 From: Melanie Date: Fri, 14 Sep 2012 00:14:39 +0200 Subject: Allow some more connections to try to ease lag. --- OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region/ClientStack') diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs index 88957ff..580c005 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs @@ -467,6 +467,8 @@ namespace OpenSim.Region.ClientStack.Linden if (llsdRequest.asset_type == "mesh") { + cost += 20; // Constant for now to test showing a price + if (llsdRequest.asset_resources == null) { client.SendAgentAlertMessage("Unable to upload asset. missing information.", false); @@ -480,7 +482,7 @@ namespace OpenSim.Region.ClientStack.Linden uint textures_cost = (uint)llsdRequest.asset_resources.texture_list.Array.Count; textures_cost *= (uint)mm.UploadCharge; - cost = textures_cost; + cost += textures_cost; } else { -- cgit v1.1 From 387e59ff7f60f2b12526eaacd93581f76abe26e1 Mon Sep 17 00:00:00 2001 From: Melanie Date: Fri, 14 Sep 2012 21:24:25 +0200 Subject: Revamp the HTTP textures handler to allow a maximum of four fetches at any time and to drop requests for avatars n longer in the scene --- .../ClientStack/Linden/Caps/GetTextureModule.cs | 223 +++++++++++++++++---- 1 file changed, 179 insertions(+), 44 deletions(-) (limited to 'OpenSim/Region/ClientStack') diff --git a/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs index 5ae9cc3..5b125ea 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs @@ -27,18 +27,13 @@ using System; using System.Collections; -using System.Collections.Specialized; -using System.Drawing; -using System.Drawing.Imaging; +using System.Collections.Generic; using System.Reflection; -using System.IO; -using System.Web; +using System.Threading; using log4net; using Nini.Config; using Mono.Addins; using OpenMetaverse; -using OpenMetaverse.StructuredData; -using OpenMetaverse.Imaging; using OpenSim.Framework; using OpenSim.Framework.Servers; using OpenSim.Framework.Servers.HttpServer; @@ -47,64 +42,73 @@ 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 { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] + /// + /// This module implements both WebFetchTextureDescendents and FetchTextureDescendents2 capabilities. + /// + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GetTextureModule")] public class GetTextureModule : INonSharedRegionModule { -// private static readonly ILog m_log = -// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private Scene m_scene; - private IAssetService m_assetService; - private bool m_Enabled = false; + private static GetTextureHandler m_getTextureHandler; + + private IAssetService m_assetService = null; - // TODO: Change this to a config option - const string REDIRECT_URL = null; + private Dictionary m_capsDict = new Dictionary(); + private static Thread[] m_workerThreads = null; - private string m_URL; + private static OpenMetaverse.BlockingQueue m_queue = + new OpenMetaverse.BlockingQueue(); #region ISharedRegionModule Members public void Initialise(IConfigSource source) { - IConfig config = source.Configs["ClientStack.LindenCaps"]; - if (config == null) - return; - - m_URL = config.GetString("Cap_GetTexture", string.Empty); - // Cap doesn't exist - if (m_URL != string.Empty) - m_Enabled = true; } public void AddRegion(Scene s) { - if (!m_Enabled) - return; - m_scene = s; + m_assetService = s.AssetService; } public void RemoveRegion(Scene s) { - if (!m_Enabled) - return; - m_scene.EventManager.OnRegisterCaps -= RegisterCaps; + m_scene.EventManager.OnDeregisterCaps -= DeregisterCaps; m_scene = null; } public void RegionLoaded(Scene s) { - if (!m_Enabled) - return; + // We'll reuse the same handler for all requests. + m_getTextureHandler = new GetTextureHandler(m_assetService); - m_assetService = m_scene.RequestModuleInterface(); m_scene.EventManager.OnRegisterCaps += RegisterCaps; + m_scene.EventManager.OnDeregisterCaps += DeregisterCaps; + + if (m_workerThreads == null) + { + m_workerThreads = new Thread[4]; + + for (uint i = 0; i < 4; i++) + { + m_workerThreads[i] = Watchdog.StartThread(DoTextureRequests, + String.Format("TextureWorkerThread{0}", i), + ThreadPriority.Normal, + false, + true, + null, + int.MaxValue); + } + } } public void PostInitialise() @@ -122,24 +126,155 @@ namespace OpenSim.Region.ClientStack.Linden #endregion - public void RegisterCaps(UUID agentID, Caps caps) + ~GetTextureModule() + { + foreach (Thread t in m_workerThreads) + t.Abort(); + } + + private class PollServiceTextureEventArgs : PollServiceEventArgs { - UUID capID = UUID.Random(); + private List requests = + new List(); + private Dictionary responses = + new Dictionary(); + + private Scene m_scene; - //caps.RegisterHandler("GetTexture", new StreamHandler("GET", "/CAPS/" + capID, ProcessGetTexture)); - if (m_URL == "localhost") + public PollServiceTextureEventArgs(UUID pId, Scene scene) : + base(null, null, null, null, pId, 30000) { -// m_log.DebugFormat("[GETTEXTURE]: /CAPS/{0} in region {1}", capID, m_scene.RegionInfo.RegionName); - caps.RegisterHandler( - "GetTexture", - new GetTextureHandler("/CAPS/" + capID + "/", m_assetService, "GetTexture", agentID.ToString())); + m_scene = scene; + + 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; + }; } - else + + public void Process() { -// m_log.DebugFormat("[GETTEXTURE]: {0} in region {1}", m_URL, m_scene.RegionInfo.RegionName); - caps.RegisterHandler("GetTexture", m_URL); + Hashtable response; + Hashtable request = null; + + try + { + lock (this.requests) + { + request = requests[0]; + requests.RemoveAt(0); + } + } + catch + { + return; + } + + UUID requestID = new UUID(request["RequestID"].ToString()); + + // If the avatar is gone, don't bother to get the texture + if (m_scene.GetScenePresence(Id) == null) + { + 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; + + responses[requestID] = response; + return; + } + + response = m_getTextureHandler.Handle(request); + + 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 + PollServiceTextureEventArgs args = new PollServiceTextureEventArgs(agentID, m_scene); + + args.Type = PollServiceEventArgs.EventType.Texture; + MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args); + + string hostName = m_scene.RegionInfo.ExternalHostName; + uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port; + string protocol = "http"; + + if (MainServer.Instance.UseSSL) + { + hostName = MainServer.Instance.SSLCommonName; + port = MainServer.Instance.SSLPort; + protocol = "https"; } + caps.RegisterHandler("GetTexture", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl)); + + m_capsDict[agentID] = capUrl; } + private void DeregisterCaps(UUID agentID, Caps caps) + { + string capUrl; + + if (m_capsDict.TryGetValue(agentID, out capUrl)) + { + MainServer.Instance.RemoveHTTPHandler("", capUrl); + m_capsDict.Remove(agentID); + } + } + + private void DoTextureRequests() + { + while (true) + { + PollServiceTextureEventArgs args = m_queue.Dequeue(); + + args.Process(); + } + } } + } -- cgit v1.1