diff --git a/OpenSim/Framework/Monitoring/JobEngine.cs b/OpenSim/Framework/Monitoring/JobEngine.cs index 7f15243521..79cd563874 100644 --- a/OpenSim/Framework/Monitoring/JobEngine.cs +++ b/OpenSim/Framework/Monitoring/JobEngine.cs @@ -137,7 +137,7 @@ namespace OpenSim.Framework.Monitoring } if (m_jobQueue != null) { - m_jobQueue .Dispose(); + m_jobQueue.Dispose(); m_jobQueue = null; } } diff --git a/OpenSim/Framework/ViewerSky.cs b/OpenSim/Framework/ViewerSky.cs index d87dacf42d..4d850cea3c 100644 --- a/OpenSim/Framework/ViewerSky.cs +++ b/OpenSim/Framework/ViewerSky.cs @@ -147,7 +147,7 @@ namespace OpenSim.Framework //this is a vector3 now, but all viewers expect a vector4, so keeping like this for now public Vector4 sunlight_color = new Vector4(0.7342f, 0.7815f, 0.9f, 0.3f); - public string Name = "Default"; + public string Name = "DefaultSky"; public float cloud_variance = 0; public float dome_offset = 0.96f; diff --git a/OpenSim/Framework/WebUtil.cs b/OpenSim/Framework/WebUtil.cs index d2338a35ff..1d95fd1d8d 100644 --- a/OpenSim/Framework/WebUtil.cs +++ b/OpenSim/Framework/WebUtil.cs @@ -53,9 +53,7 @@ namespace OpenSim.Framework /// public static class WebUtil { - private static readonly ILog m_log = - LogManager.GetLogger( - MethodBase.GetCurrentMethod().DeclaringType); + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); /// /// Control the printing of certain debug messages. diff --git a/OpenSim/Region/ClientStack/Linden/Caps/GetAssetsModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/GetAssetsModule.cs index dcf9cd4eef..4b60a93d71 100755 --- a/OpenSim/Region/ClientStack/Linden/Caps/GetAssetsModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/GetAssetsModule.cs @@ -232,7 +232,6 @@ namespace OpenSim.Region.ClientStack.Linden private HashSet dropedResponses = new HashSet(); private Scene m_scene; - private ScenePresence m_presence; public PollServiceAssetEventArgs(string uri, UUID pId, Scene scene) : base(null, uri, null, null, null, null, pId, int.MaxValue) { @@ -245,20 +244,19 @@ namespace OpenSim.Region.ClientStack.Linden APollResponse response; if (responses.TryGetValue(requestID, out response)) { - if (m_presence == null) - m_presence = m_scene.GetScenePresence(pId); + ScenePresence sp = m_scene.GetScenePresence(pId); - if (m_presence == null || m_presence.IsDeleted) + if (sp == null || sp.IsDeleted) return true; OSHttpResponse resp = response.osresponse; if(Util.GetTimeStamp() - resp.RequestTS > (resp.RawBufferLen > 2000000 ? 200 : 90)) - return m_presence.CapCanSendAsset(2, resp.RawBufferLen); + return sp.CapCanSendAsset(2, resp.RawBufferLen); if (resp.Priority > 1) - return m_presence.CapCanSendAsset(1, resp.RawBufferLen); - return m_presence.CapCanSendAsset(2, resp.RawBufferLen); + return sp.CapCanSendAsset(1, resp.RawBufferLen); + return sp.CapCanSendAsset(2, resp.RawBufferLen); } return false; } diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs index 21e61a73b2..afdcf4786c 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs @@ -748,9 +748,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_nextOnQueueEmpty = start + MIN_CALLBACK_MS; // Asynchronously run the callback - if (m_udpServer.OqrEngine.IsRunning) - m_udpServer.OqrEngine.QueueJob(AgentID.ToString(), () => FireQueueEmpty(categories)); - else + // avoid stupid memory leak + //if (m_udpServer.OqrEngine.IsRunning) + // m_udpServer.OqrEngine.QueueJob(AgentID.ToString(), () => FireQueueEmpty(categories)); + //else Util.FireAndForget(FireQueueEmpty, categories, "LLUDPClient.BeginFireQueueEmpty"); } } @@ -764,16 +765,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// signature public void FireQueueEmpty(object o) { - ThrottleOutPacketTypeFlags categories = (ThrottleOutPacketTypeFlags)o; QueueEmpty callback = OnQueueEmpty; - if (callback != null) { - // if (m_udpServer.IsRunningOutbound) - // { + ThrottleOutPacketTypeFlags categories = (ThrottleOutPacketTypeFlags)o; try { callback(categories); } catch (Exception e) { m_log.Error("[LLUDPCLIENT]: OnQueueEmpty(" + categories + ") threw an exception: " + e.Message, e); } - // } } m_isQueueEmptyRunning = false; diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs index 02c73bdfc1..5b2d15aa36 100755 --- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs @@ -28,9 +28,8 @@ using System; using System.IO; using System.Collections.Generic; -using System.Linq; +using System.Collections.Concurrent; using System.Reflection; -using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; using System.Text; using System.Threading; @@ -40,7 +39,6 @@ using Nini.Config; using Mono.Addins; using OpenMetaverse; using OpenSim.Framework; -using OpenSim.Framework.Console; using OpenSim.Framework.Monitoring; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; @@ -53,6 +51,12 @@ namespace OpenSim.Region.CoreModules.Asset [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "FlotsamAssetCache")] public class FlotsamAssetCache : ISharedRegionModule, IAssetCache, IAssetService { + private struct WriteAssetInfo + { + public string filename; + public AssetBase asset; + } + private static readonly ILog m_log = LogManager.GetLogger( MethodBase.GetCurrentMethod().DeclaringType); private bool m_Enabled; @@ -76,6 +80,8 @@ namespace OpenSim.Region.CoreModules.Asset private ulong m_weakRefHits; private static HashSet m_CurrentlyWriting = new HashSet(); + private static BlockingCollection m_assetFileWriteQueue = null; + private static CancellationTokenSource m_cancelSource; private bool m_FileCacheEnabled = true; @@ -116,8 +122,6 @@ namespace OpenSim.Region.CoreModules.Asset m_InvalidChars = invalidChars.ToArray(); } - private static JobEngine m_DiskWriterEngine = null; - public Type ReplaceableInterface { get { return null; } @@ -219,6 +223,19 @@ namespace OpenSim.Region.CoreModules.Asset public void Close() { + if(m_Scenes.Count <= 0) + { + if (m_assetFileWriteQueue != null) + { + m_assetFileWriteQueue.Dispose(); + m_assetFileWriteQueue = null; + } + if(m_cancelSource != null) + { + m_cancelSource.Dispose(); + m_cancelSource = null; + } + } } public void AddRegion(Scene scene) @@ -238,13 +255,16 @@ namespace OpenSim.Region.CoreModules.Asset m_Scenes.Remove(scene); lock(timerLock) { - if(m_timerRunning && m_Scenes.Count <= 0) + if(m_Scenes.Count <= 0) { - m_timerRunning = false; - m_CacheCleanTimer.Stop(); - m_CacheCleanTimer.Close(); - if (m_FileCacheEnabled && m_DiskWriterEngine != null && m_DiskWriterEngine.IsRunning) - m_DiskWriterEngine.Stop(); + if (m_timerRunning) + { + m_timerRunning = false; + m_CacheCleanTimer.Stop(); + m_CacheCleanTimer.Close(); + } + if (m_FileCacheEnabled && m_assetFileWriteQueue != null) + m_cancelSource.Cancel(); } } } @@ -270,15 +290,31 @@ namespace OpenSim.Region.CoreModules.Asset } } - if(m_DiskWriterEngine == null) + if (m_FileCacheEnabled && m_assetFileWriteQueue == null) { - m_DiskWriterEngine = new JobEngine("FlotsamWriter", "FlotsamWriter"); - m_DiskWriterEngine.Start(); + m_assetFileWriteQueue = new BlockingCollection(); + m_cancelSource = new CancellationTokenSource(); + WorkManager.RunInThreadPool(processWrites, null, "FloatsamCacheWriter", false); } } } } + private void processWrites(object o) + { + try + { + while(true) + { + if(m_assetFileWriteQueue.TryTake(out WriteAssetInfo wai,-1, m_cancelSource.Token)) + { + WriteFileCache(wai.filename,wai.asset,false); + } + } + } + catch{ } + } + //////////////////////////////////////////////////////////// // IAssetCache // @@ -302,6 +338,9 @@ namespace OpenSim.Region.CoreModules.Asset private void UpdateFileCache(string key, AssetBase asset, bool replace = false) { + if(m_assetFileWriteQueue == null) + return; + string filename = GetFileName(key); try @@ -323,8 +362,11 @@ namespace OpenSim.Region.CoreModules.Asset m_CurrentlyWriting.Add(filename); } - // weakreferences should hold and return the asset while async write happens - m_DiskWriterEngine?.QueueJob("", delegate { WriteFileCache(filename, asset, replace); }); + WriteAssetInfo wai = new WriteAssetInfo(); + wai.filename = filename; + wai.asset = asset; + if (m_assetFileWriteQueue != null) + m_assetFileWriteQueue.Add(wai); } catch (Exception e) { diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 8e1b6f6985..34c552e66f 100755 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1664,20 +1664,24 @@ namespace OpenSim.Region.Framework.Scenes */ if (Frame % (m_update_coarse_locations) == 0 && !m_sendingCoarseLocations) { - m_sendingCoarseLocations = true; - WorkManager.RunInThreadPool( - delegate - { - List coarseLocations; - List avatarUUIDs; - SceneGraph.GetCoarseLocations(out coarseLocations, out avatarUUIDs, 60); - // Send coarse locations to clients - ForEachScenePresence(delegate(ScenePresence presence) + if(GetNumberOfClients() > 0) + { + m_sendingCoarseLocations = true; + WorkManager.RunInThreadPool( + delegate { - presence.SendCoarseLocations(coarseLocations, avatarUUIDs); - }); - m_sendingCoarseLocations = false; - }, null, string.Format("SendCoarseLocations ({0})", Name)); + List coarseLocations; + List avatarUUIDs; + SceneGraph.GetCoarseLocations(out coarseLocations, out avatarUUIDs, 60); + // Send coarse locations to clients + ForEachScenePresence(delegate(ScenePresence presence) + { + if(!presence.IsNPC) + presence.SendCoarseLocations(coarseLocations, avatarUUIDs); + }); + m_sendingCoarseLocations = false; + }, null, string.Format("SendCoarseLocations ({0})", Name)); + } } // Get the simulation frame time that the avatar force input diff --git a/OpenSim/Server/Base/ServerUtils.cs b/OpenSim/Server/Base/ServerUtils.cs index 5fc3d72bd6..9a374d19e6 100644 --- a/OpenSim/Server/Base/ServerUtils.cs +++ b/OpenSim/Server/Base/ServerUtils.cs @@ -564,6 +564,29 @@ namespace OpenSim.Server.Base return new Dictionary(); } + public static Dictionary ParseXmlResponse(Stream src) + { + //m_log.DebugFormat("[XXX]: received xml string: {0}", data); + + try + { + XmlReaderSettings xset = new XmlReaderSettings() { IgnoreWhitespace = true, IgnoreComments = true, ConformanceLevel = ConformanceLevel.Fragment, CloseInput = true }; + XmlParserContext xpc = new XmlParserContext(null, null, null, XmlSpace.None); + xpc.Encoding = Util.UTF8NoBomEncoding; + using (XmlReader xr = XmlReader.Create(src, xset, xpc)) + { + if (!xr.ReadToFollowing("ServerResponse")) + return new Dictionary(); + return ScanXmlResponse(xr); + } + } + catch (Exception e) + { + m_log.DebugFormat("[serverUtils.ParseXmlResponse]: failed error: {0}", e.Message); + } + return new Dictionary(); + } + public static IConfig GetConfig(string configFile, string configName) { IConfig config; diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini index 9ec83a1ad4..a3df908663 100644 --- a/bin/OpenSimDefaults.ini +++ b/bin/OpenSimDefaults.ini @@ -770,7 +770,7 @@ Cap_DispatchRegionInfo = "" Cap_EstateAccess = "localhost" //Cap_EstateChangeInfo = "localhost" broken on viewers - Cap_EnvironmentSettings = "localhost" + Cap_EnvironmentSettings = "localhost" // this also controls ExtEnviroment cap Cap_EventQueueGet = "localhost" Cap_FetchInventory = "" Cap_ObjectMedia = "localhost"