From 72d1d96c5c9b8f9f31e21ef4a3d542a27fc6c3f8 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 3 Dec 2014 18:58:55 +0000 Subject: Always close script linemap file after reading and always dispose of other streams in the script engine even if exceptions are thrown. --- .../ScriptEngine/Shared/CodeTools/Compiler.cs | 49 +++++++++++----------- .../ScriptEngine/Shared/Instance/ScriptInstance.cs | 9 ++-- 2 files changed, 29 insertions(+), 29 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs index 9379f8f..de5f92d 100644 --- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs +++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs @@ -663,9 +663,8 @@ namespace SecondLife try { - FileStream fs = File.Open(assembly, FileMode.Open, FileAccess.Read); - fs.Read(data, 0, data.Length); - fs.Close(); + using (FileStream fs = File.Open(assembly, FileMode.Open, FileAccess.Read)) + fs.Read(data, 0, data.Length); } catch (Exception) { @@ -680,9 +679,8 @@ namespace SecondLife Byte[] buf = Encoding.ASCII.GetBytes(filetext); - FileStream sfs = File.Create(assembly + ".text"); - sfs.Write(buf, 0, buf.Length); - sfs.Close(); + using (FileStream sfs = File.Create(assembly + ".text")) + sfs.Write(buf, 0, buf.Length); return assembly; } @@ -775,7 +773,6 @@ namespace SecondLife return message; } - private static void WriteMapFile(string filename, Dictionary, KeyValuePair> linemap) { string mapstring = String.Empty; @@ -787,40 +784,42 @@ namespace SecondLife } Byte[] mapbytes = Encoding.ASCII.GetBytes(mapstring); - FileStream mfs = File.Create(filename); - mfs.Write(mapbytes, 0, mapbytes.Length); - mfs.Close(); - } + using (FileStream mfs = File.Create(filename)) + mfs.Write(mapbytes, 0, mapbytes.Length); + } private static Dictionary, KeyValuePair> ReadMapFile(string filename) { Dictionary, KeyValuePair> linemap; try { - StreamReader r = File.OpenText(filename); - linemap = new Dictionary, KeyValuePair>(); - - string line; - while ((line = r.ReadLine()) != null) + using (StreamReader r = File.OpenText(filename)) { - String[] parts = line.Split(new Char[] { ',' }); - int kk = System.Convert.ToInt32(parts[0]); - int kv = System.Convert.ToInt32(parts[1]); - int vk = System.Convert.ToInt32(parts[2]); - int vv = System.Convert.ToInt32(parts[3]); + linemap = new Dictionary, KeyValuePair>(); - KeyValuePair k = new KeyValuePair(kk, kv); - KeyValuePair v = new KeyValuePair(vk, vv); + string line; + while ((line = r.ReadLine()) != null) + { + String[] parts = line.Split(new Char[] { ',' }); + int kk = System.Convert.ToInt32(parts[0]); + int kv = System.Convert.ToInt32(parts[1]); + int vk = System.Convert.ToInt32(parts[2]); + int vv = System.Convert.ToInt32(parts[3]); + + KeyValuePair k = new KeyValuePair(kk, kv); + KeyValuePair v = new KeyValuePair(vk, vv); - linemap[k] = v; + linemap[k] = v; + } } } catch { linemap = new Dictionary, KeyValuePair>(); } + return linemap; } } -} +} \ No newline at end of file diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs index 9da2168..637c556 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs @@ -1065,10 +1065,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance { try { - FileStream fs = File.Create(Path.Combine(Path.GetDirectoryName(assembly), ItemID.ToString() + ".state")); - Byte[] buf = Util.UTF8NoBomEncoding.GetBytes(xml); - fs.Write(buf, 0, buf.Length); - fs.Close(); + using (FileStream fs = File.Create(Path.Combine(Path.GetDirectoryName(assembly), ItemID.ToString() + ".state"))) + { + Byte[] buf = Util.UTF8NoBomEncoding.GetBytes(xml); + fs.Write(buf, 0, buf.Length); + } } catch(Exception) { -- cgit v1.1 From 805b7ccb3e45c5233dd771a5e4a2fe01a5dfb4fc Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 3 Dec 2014 20:35:49 +0000 Subject: minor: improve logged error in XEngine.SetXmlState if there was a problem writing the linemap. The previous error report of already exists is inaccurate since existing files do get overwritten. --- OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index a4113d6..e5c11d8 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -2155,7 +2155,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine catch (IOException ex) { // if there already exists a file at that location, it may be locked. - m_log.ErrorFormat("[XEngine]: Linemap file {0} already exists! {1}", mappath, ex.Message); + m_log.Error( + string.Format("[XEngine]: Linemap file {0} could not be written. Exception ", mappath), ex); } } } -- cgit v1.1 From c3c05a86939de9669c1065d0a738a2a9b0f30c27 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 3 Dec 2014 20:48:17 +0000 Subject: Reintroduce general xengine extra debugging log level. This can be controlled at runtime with the command "debug xengine log ", as with similar commands. If log level is 1 then every script load is logged. This means the section in OpenSim.exe.config is no longer needed to avoid log spam on regions with many scripts and can be removed. --- OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | 63 +++++++++++++------------- 1 file changed, 32 insertions(+), 31 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index e5c11d8..bd11451 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -70,7 +70,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine /// /// If DebugLevel >= 1, then we log every time that a script is started. /// -// public int DebugLevel { get; set; } + public int DebugLevel { get; set; } private SmartThreadPool m_ThreadPool; private int m_MaxScriptQueue; @@ -403,12 +403,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine + "Level >= 2, log event invocations.\n", HandleDebugScriptLogCommand); -// MainConsole.Instance.Commands.AddCommand( -// "Debug", false, "debug xengine", "debug xengine []", -// "Turn on detailed xengine debugging.", -// "If level <= 0, then no extra logging is done.\n" -// + "If level >= 1, then we log every time that a script is started.", -// HandleDebugLevelCommand); + MainConsole.Instance.Commands.AddCommand( + "Debug", false, "debug xengine log", "debug xengine log []", + "Turn on detailed xengine debugging.", + "If level <= 0, then no extra logging is done.\n" + + "If level >= 1, then we log every time that a script is started.", + HandleDebugLevelCommand); } private void HandleDebugScriptLogCommand(string module, string[] args) @@ -451,26 +451,26 @@ namespace OpenSim.Region.ScriptEngine.XEngine /// /// /// -// private void HandleDebugLevelCommand(string module, string[] args) -// { -// if (args.Length == 3) -// { -// int newDebug; -// if (int.TryParse(args[2], out newDebug)) -// { -// DebugLevel = newDebug; -// MainConsole.Instance.OutputFormat("Debug level set to {0}", newDebug); -// } -// } -// else if (args.Length == 2) -// { -// MainConsole.Instance.OutputFormat("Current debug level is {0}", DebugLevel); -// } -// else -// { -// MainConsole.Instance.Output("Usage: debug xengine 0..1"); -// } -// } + private void HandleDebugLevelCommand(string module, string[] args) + { + if (args.Length <= 4) + { + int newDebug; + if (ConsoleUtil.TryParseConsoleNaturalInt(MainConsole.Instance, args[3], out newDebug)) + { + DebugLevel = newDebug; + MainConsole.Instance.OutputFormat("Debug level set to {0} in XEngine for region {1}", newDebug, m_Scene.Name); + } + } + else if (args.Length == 3) + { + MainConsole.Instance.OutputFormat("Current debug level is {0}", DebugLevel); + } + else + { + MainConsole.Instance.Output("Usage: debug xengine log "); + } + } /// /// Parse the raw item id into a script instance from the command params if it's present. @@ -1148,10 +1148,11 @@ namespace OpenSim.Region.ScriptEngine.XEngine return false; } - m_log.DebugFormat( - "[XEngine]: Loading script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}", - part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID, - part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName); + if (DebugLevel > 0) + m_log.DebugFormat( + "[XEngine]: Loading script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}", + part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID, + part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName); UUID assetID = item.AssetID; -- cgit v1.1 From d34ad345d5f6a8e57b4262e72b38e60e8623de30 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 3 Dec 2014 21:08:43 +0000 Subject: minor: If we are recompiling scripts in response to a ScriptStopStrategy config change (a rare situation), then explicitly log this for debug purposes. --- OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'OpenSim') diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index bd11451..752b397 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -1349,7 +1349,15 @@ namespace OpenSim.Region.ScriptEngine.XEngine // simulator session if the script halt strategy has been changed. Instead, we'll continue with // the existing DLL and the new one will be used in the next simulator session. if (recompile) + { + m_log.DebugFormat( + "[XEngine]: Recompiling script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5} to switch it to {6} termination. Will be active on next restart.", + part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID, + part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.Name, + m_coopTermination ? "co-op" : "abort"); + m_Compiler.PerformScriptCompile(script, assetID.ToString(), item.OwnerID, true, out assemblyPath, out linemap); + } instance = new ScriptInstance(this, part, item, -- cgit v1.1 From 2d2aa6e07645b3b9f1577b41d0f73803ccafba80 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 3 Dec 2014 21:40:39 +0000 Subject: minor: Just have one message that displays successful registration of a region with its parameters rather than 2 --- OpenSim/Region/Framework/Scenes/Scene.cs | 10 +++++----- OpenSim/Services/GridService/GridService.cs | 6 ++++-- 2 files changed, 9 insertions(+), 7 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index f7c12d6..0c83186 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2042,11 +2042,11 @@ namespace OpenSim.Region.Framework.Scenes GridRegion region = new GridRegion(RegionInfo); string error = GridService.RegisterRegion(RegionInfo.ScopeID, region); - m_log.DebugFormat("{0} RegisterRegionWithGrid. name={1},id={2},loc=<{3},{4}>,size=<{5},{6}>", - LogHeader, m_regionName, - RegionInfo.RegionID, - RegionInfo.RegionLocX, RegionInfo.RegionLocY, - RegionInfo.RegionSizeX, RegionInfo.RegionSizeY); +// m_log.DebugFormat("[SCENE]: RegisterRegionWithGrid. name={0},id={1},loc=<{2},{3}>,size=<{4},{5}>", +// m_regionName, +// RegionInfo.RegionID, +// RegionInfo.RegionLocX, RegionInfo.RegionLocY, +// RegionInfo.RegionSizeX, RegionInfo.RegionSizeY); if (error != String.Empty) throw new Exception(error); diff --git a/OpenSim/Services/GridService/GridService.cs b/OpenSim/Services/GridService/GridService.cs index e8a545c..29723d8 100644 --- a/OpenSim/Services/GridService/GridService.cs +++ b/OpenSim/Services/GridService/GridService.cs @@ -317,8 +317,10 @@ namespace OpenSim.Services.GridService m_log.DebugFormat("[GRID SERVICE]: Database exception: {0}", e); } - m_log.DebugFormat("[GRID SERVICE]: Region {0} ({1}) registered successfully at {2}-{3} with flags {4}", - regionInfos.RegionName, regionInfos.RegionID, regionInfos.RegionCoordX, regionInfos.RegionCoordY, + m_log.DebugFormat + ("[GRID SERVICE]: Region {0} ({1}, {2}x{3}) registered at {4},{5} with flags {6}", + regionInfos.RegionName, regionInfos.RegionID, regionInfos.RegionSizeX, regionInfos.RegionSizeY, + regionInfos.RegionCoordX, regionInfos.RegionCoordY, (OpenSim.Framework.RegionFlags)flags); return String.Empty; -- cgit v1.1 From 5861401faa39587196c86045decbe4329b59aee8 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 3 Dec 2014 21:44:22 +0000 Subject: Remove long unused region parameters from SceneBase. Some of these weren't even being set. Region parameters come from Scene.RegionInfo instead. --- OpenSim/Region/Framework/Scenes/Scene.cs | 1 - OpenSim/Region/Framework/Scenes/SceneBase.cs | 4 ---- 2 files changed, 5 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 0c83186..21d47aa 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -823,7 +823,6 @@ namespace OpenSim.Region.Framework.Scenes m_sceneGridService = sceneGridService; m_SimulationDataService = simDataService; m_EstateDataService = estateDataService; - m_regionHandle = RegionInfo.RegionHandle; m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this); m_asyncSceneObjectDeleter.Enabled = true; diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs index aaddce6..6f172e7 100644 --- a/OpenSim/Region/Framework/Scenes/SceneBase.cs +++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs @@ -145,10 +145,6 @@ namespace OpenSim.Region.Framework.Scenes get { return 1.0f; } } - protected ulong m_regionHandle; - protected string m_regionName; - protected RegionInfo m_regInfo; - public ITerrainChannel Heightmap; /// -- cgit v1.1 From c36bfdc60f62b53e87de0ed3dbbd8e63c8a8f007 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 4 Dec 2014 01:46:00 +0000 Subject: Don't worry about checking FlotsamAssetCache.m_CurrentlyWriting when updating access time. The majority of updates won't be for anything currently writing and any sharing exception from an actual clash can be caught and ignored anyway. --- OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs index fe9a17d..bc5b39b 100644 --- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs @@ -256,16 +256,9 @@ namespace OpenSim.Region.CoreModules.Asset // If the file is already cached, don't cache it, just touch it so access time is updated if (File.Exists(filename)) { - // We don't really want to know about sharing - // violations here. If the file is locked, then - // the other thread has updated the time for us. try { - lock (m_CurrentlyWriting) - { - if (!m_CurrentlyWriting.Contains(filename)) - File.SetLastAccessTime(filename, DateTime.Now); - } + File.SetLastAccessTime(filename, DateTime.Now); } catch { -- cgit v1.1 From ad91143880582bbb9dd956ddce7ab1dc9a4215b0 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 4 Dec 2014 01:51:01 +0000 Subject: refactor: breakout flotasm cache last file access time to separate UpdateFileLastAccessTime() method for imminent reuse. --- .../Region/CoreModules/Asset/FlotsamAssetCache.cs | 26 ++++++++++++++++------ 1 file changed, 19 insertions(+), 7 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs index bc5b39b..7780568 100644 --- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs @@ -256,13 +256,7 @@ namespace OpenSim.Region.CoreModules.Asset // If the file is already cached, don't cache it, just touch it so access time is updated if (File.Exists(filename)) { - try - { - File.SetLastAccessTime(filename, DateTime.Now); - } - catch - { - } + UpdateFileLastAccessTime(filename); } else { @@ -322,6 +316,24 @@ namespace OpenSim.Region.CoreModules.Asset } /// + /// Updates the cached file with the current time. + /// + /// Filename. + /// true, if the update was successful, false otherwise. + private bool UpdateFileLastAccessTime(string filename) + { + try + { + File.SetLastAccessTime(filename, DateTime.Now); + return true; + } + catch + { + return false; + } + } + + /// /// Try to get an asset from the in-memory cache. /// /// -- cgit v1.1 From 9dbe99af0fda41060e1123c65a3aca87618d0e89 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 4 Dec 2014 01:53:42 +0000 Subject: If "fcache assets" is executed, don't stop with an exception if there's an access violation if another thread is operating on the file at the same time. Resolves one issue from http://opensimulator.org/mantis/view.php?id=7271 --- OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs index 7780568..24d5d00 100644 --- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs @@ -795,7 +795,7 @@ namespace OpenSim.Region.CoreModules.Asset if (File.Exists(filename)) { - File.SetLastAccessTime(filename, DateTime.Now); + UpdateFileLastAccessTime(filename); } else if (storeUncached) { @@ -811,7 +811,6 @@ namespace OpenSim.Region.CoreModules.Asset }); } - return uniqueUuids.Count; } -- cgit v1.1 From bee3f203cd93ed3816ff9d24ea04d4aa898cf779 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 4 Dec 2014 22:52:46 +0000 Subject: Allow scripts in attachments on an owned NPC to call NPC functions on that NPC --- OpenSim/Region/Framework/Interfaces/INPCModule.cs | 11 +++++++++++ OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs | 9 ++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Framework/Interfaces/INPCModule.cs b/OpenSim/Region/Framework/Interfaces/INPCModule.cs index d5dcddd..478833e 100644 --- a/OpenSim/Region/Framework/Interfaces/INPCModule.cs +++ b/OpenSim/Region/Framework/Interfaces/INPCModule.cs @@ -122,6 +122,17 @@ namespace OpenSim.Region.Framework.Interfaces /// /// Check if the caller has permission to manipulate the given NPC. /// + /// + /// A caller has permission if + /// * An NPC exists with the given npcID. + /// * The caller UUID given is UUID.Zero. + /// * The avatar is unowned (owner is UUID.Zero). + /// * The avatar is owned and the owner and callerID match. + /// * The avatar is owned and the callerID matches its agentID. + /// + /// + /// + /// true if they do, false if they don't. /// /// /// diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs index 95e59ab..b834619 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs @@ -441,13 +441,20 @@ namespace OpenSim.Region.OptionalModules.World.NPC /// /// Check if the caller has permission to manipulate the given NPC. /// + /// + /// A caller has permission if + /// * The caller UUID given is UUID.Zero. + /// * The avatar is unowned (owner is UUID.Zero). + /// * The avatar is owned and the owner and callerID match. + /// * The avatar is owned and the callerID matches its agentID. + /// /// /// /// true if they do, false if they don't. private bool CheckPermissions(NPCAvatar av, UUID callerID) { return callerID == UUID.Zero || av.OwnerID == UUID.Zero || - av.OwnerID == callerID; + av.OwnerID == callerID || av.AgentId == callerID; } } } \ No newline at end of file -- cgit v1.1 From 9208fb5d543e5dd226d8d900c78a5056fea4f022 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 4 Dec 2014 23:55:59 +0000 Subject: refactor: Make IteratingUUIDGatherer take a dictionary in its constructor like UUIDGatherer, so we can deal with future cases where the dictionary may already be pre-populated. --- .../EntityTransfer/HGEntityTransferModule.cs | 6 ++-- OpenSim/Region/Framework/Scenes/UuidGatherer.cs | 32 ++++++++++++++++------ 2 files changed, 26 insertions(+), 12 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs index 97267c1..fc932b0 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs @@ -604,7 +604,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer // "[HG ENTITY TRANSFER MODULE]: Incoming attachment {0} for HG user {1} with asset service {2}", // so.Name, so.AttachedAvatar, url); - IteratingHGUuidGatherer uuidGatherer = new IteratingHGUuidGatherer(Scene.AssetService, url); + IDictionary ids = new Dictionary(); + IteratingHGUuidGatherer uuidGatherer + = new IteratingHGUuidGatherer(Scene.AssetService, url, ids); uuidGatherer.RecordAssetUuids(so); while (!uuidGatherer.Complete) @@ -632,8 +634,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer } } - IDictionary ids = uuidGatherer.GetGatheredUuids(); - // m_log.DebugFormat( // "[HG ENTITY TRANSFER]: Fetching {0} assets for attachment {1} for HG user {2} with asset service {3}", // ids.Count, so.Name, so.OwnerID, url); diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs index 2450cdb..cacacf8 100644 --- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs +++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs @@ -648,6 +648,15 @@ namespace OpenSim.Region.Framework.Scenes } } + /// + /// Gather uuids for a given entity. + /// + /// + /// This does a deep inspection of the entity to retrieve all the assets it uses (whether as textures, as scripts + /// contained in inventory, as scripts contained in objects contained in another object's inventory, etc. Assets + /// are only retrieved when they are necessary to carry out the inspection (i.e. a serialized object needs to be + /// retrieved to work out which assets it references). + /// public class IteratingUuidGatherer { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -678,20 +687,25 @@ namespace OpenSim.Region.Framework.Scenes protected Queue m_assetUuidsToInspect; - public IteratingUuidGatherer(IAssetService assetService) + /// + /// Initializes a new instance of the class. + /// + /// + /// Asset service. + /// + /// + /// Gathered UUIDs will be collected in this dictinaory. + /// It can be pre-populated if you want to stop the gatherer from analyzing assets that have already been fetched and inspected. + /// + public IteratingUuidGatherer(IAssetService assetService, IDictionary collector) { m_assetService = assetService; - m_gatheredAssetUuids = new Dictionary(); + m_gatheredAssetUuids = collector; // FIXME: Not efficient for searching, can improve. m_assetUuidsToInspect = new Queue(); } - public IDictionary GetGatheredUuids() - { - return new Dictionary(m_gatheredAssetUuids); - } - public bool AddAssetUuidToInspect(UUID uuid) { if (m_assetUuidsToInspect.Contains(uuid)) @@ -1147,8 +1161,8 @@ namespace OpenSim.Region.Framework.Scenes protected string m_assetServerURL; - public IteratingHGUuidGatherer(IAssetService assetService, string assetServerURL) - : base(assetService) + public IteratingHGUuidGatherer(IAssetService assetService, string assetServerURL, IDictionary collector) + : base(assetService, collector) { m_assetServerURL = assetServerURL; if (!m_assetServerURL.EndsWith("/") && !m_assetServerURL.EndsWith("=")) -- cgit v1.1 From b0ff3236be6a2ec55444944232d2a36d993a6a91 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 5 Dec 2014 00:09:01 +0000 Subject: Make "fache assets" console command more efficient by only updating access times on each cached asset once, not for every reference. --- .../Region/CoreModules/Asset/FlotsamAssetCache.cs | 41 +++++++++++++--------- 1 file changed, 24 insertions(+), 17 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs index 24d5d00..6564b4d 100644 --- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs @@ -776,8 +776,8 @@ namespace OpenSim.Region.CoreModules.Asset { UuidGatherer gatherer = new UuidGatherer(m_AssetService); - HashSet uniqueUuids = new HashSet(); - Dictionary assets = new Dictionary(); + Dictionary assetIdsToCheck = new Dictionary(); + Dictionary assetsFound = new Dictionary(); foreach (Scene s in m_Scenes) { @@ -785,33 +785,40 @@ namespace OpenSim.Region.CoreModules.Asset s.ForEachSOG(delegate(SceneObjectGroup e) { - gatherer.GatherAssetUuids(e, assets); + gatherer.GatherAssetUuids(e, assetIdsToCheck); - foreach (UUID assetID in assets.Keys) + foreach (UUID assetID in assetIdsToCheck.Keys) { - uniqueUuids.Add(assetID); - - string filename = GetFileName(assetID.ToString()); - - if (File.Exists(filename)) + if (!assetsFound.ContainsKey(assetID)) { - UpdateFileLastAccessTime(filename); + string filename = GetFileName(assetID.ToString()); + + if (File.Exists(filename)) + { + UpdateFileLastAccessTime(filename); + } + else if (storeUncached) + { + AssetBase cachedAsset = m_AssetService.Get(assetID.ToString()); + if (cachedAsset == null && assetIdsToCheck[assetID] != (sbyte)AssetType.Unknown) + assetsFound[assetID] = false; + else + assetsFound[assetID] = true; + } } - else if (storeUncached) + else if (!assetsFound[assetID]) { - AssetBase cachedAsset = m_AssetService.Get(assetID.ToString()); - if (cachedAsset == null && assets[assetID] != (sbyte)AssetType.Unknown) - m_log.DebugFormat( + m_log.DebugFormat( "[FLOTSAM ASSET CACHE]: Could not find asset {0}, type {1} referenced by object {2} at {3} in scene {4} when pre-caching all scene assets", - assetID, assets[assetID], e.Name, e.AbsolutePosition, s.Name); + assetID, assetIdsToCheck[assetID], e.Name, e.AbsolutePosition, s.Name); } } - assets.Clear(); + assetIdsToCheck.Clear(); }); } - return uniqueUuids.Count; + return assetsFound.Count; } /// -- cgit v1.1 From f3ab7c0f5c7675bd33cc5725c278318bef25b4aa Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 5 Dec 2014 00:21:42 +0000 Subject: refactor: rename IteratingUuidGather.AddAssetUuidToInspect() and RecordAssetUuids() to AddForInspection() as this properly describes what both of these methods do. --- .../EntityTransfer/HGEntityTransferModule.cs | 2 +- OpenSim/Region/Framework/Scenes/UuidGatherer.cs | 233 +++++++++++---------- 2 files changed, 120 insertions(+), 115 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs index fc932b0..2ddb599 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs @@ -607,7 +607,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer IDictionary ids = new Dictionary(); IteratingHGUuidGatherer uuidGatherer = new IteratingHGUuidGatherer(Scene.AssetService, url, ids); - uuidGatherer.RecordAssetUuids(so); + uuidGatherer.AddForInspection(so); while (!uuidGatherer.Complete) { diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs index cacacf8..2c5353f 100644 --- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs +++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs @@ -706,7 +706,12 @@ namespace OpenSim.Region.Framework.Scenes m_assetUuidsToInspect = new Queue(); } - public bool AddAssetUuidToInspect(UUID uuid) + /// + /// Adds the asset uuid for inspection during the gathering process. + /// + /// true, if for inspection was added, false otherwise. + /// UUID. + public bool AddForInspection(UUID uuid) { if (m_assetUuidsToInspect.Contains(uuid)) return false; @@ -715,6 +720,107 @@ namespace OpenSim.Region.Framework.Scenes return true; } + + /// + /// Gather all the asset uuids associated with a given object. + /// + /// + /// This includes both those directly associated with + /// it (e.g. face textures) and recursively, those of items within it's inventory (e.g. objects contained + /// within this object). + /// + /// The scene object for which to gather assets + public void AddForInspection(SceneObjectGroup sceneObject) + { + // m_log.DebugFormat( + // "[ASSET GATHERER]: Getting assets for object {0}, {1}", sceneObject.Name, sceneObject.UUID); + + SceneObjectPart[] parts = sceneObject.Parts; + for (int i = 0; i < parts.Length; i++) + { + SceneObjectPart part = parts[i]; + + // m_log.DebugFormat( + // "[ARCHIVER]: Getting part {0}, {1} for object {2}", part.Name, part.UUID, sceneObject.UUID); + + try + { + Primitive.TextureEntry textureEntry = part.Shape.Textures; + if (textureEntry != null) + { + // Get the prim's default texture. This will be used for faces which don't have their own texture + if (textureEntry.DefaultTexture != null) + RecordTextureEntryAssetUuids(textureEntry.DefaultTexture); + + if (textureEntry.FaceTextures != null) + { + // Loop through the rest of the texture faces (a non-null face means the face is different from DefaultTexture) + foreach (Primitive.TextureEntryFace texture in textureEntry.FaceTextures) + { + if (texture != null) + RecordTextureEntryAssetUuids(texture); + } + } + } + + // If the prim is a sculpt then preserve this information too + if (part.Shape.SculptTexture != UUID.Zero) + m_gatheredAssetUuids[part.Shape.SculptTexture] = (sbyte)AssetType.Texture; + + if (part.Shape.ProjectionTextureUUID != UUID.Zero) + m_gatheredAssetUuids[part.Shape.ProjectionTextureUUID] = (sbyte)AssetType.Texture; + + if (part.CollisionSound != UUID.Zero) + m_gatheredAssetUuids[part.CollisionSound] = (sbyte)AssetType.Sound; + + if (part.ParticleSystem.Length > 0) + { + try + { + Primitive.ParticleSystem ps = new Primitive.ParticleSystem(part.ParticleSystem, 0); + if (ps.Texture != UUID.Zero) + m_gatheredAssetUuids[ps.Texture] = (sbyte)AssetType.Texture; + } + catch (Exception) + { + m_log.WarnFormat( + "[UUID GATHERER]: Could not check particle system for part {0} {1} in object {2} {3} since it is corrupt. Continuing.", + part.Name, part.UUID, sceneObject.Name, sceneObject.UUID); + } + } + + TaskInventoryDictionary taskDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone(); + + // Now analyze this prim's inventory items to preserve all the uuids that they reference + foreach (TaskInventoryItem tii in taskDictionary.Values) + { + // m_log.DebugFormat( + // "[ARCHIVER]: Analysing item {0} asset type {1} in {2} {3}", + // tii.Name, tii.Type, part.Name, part.UUID); + + if (!m_gatheredAssetUuids.ContainsKey(tii.AssetID)) + AddForInspection(tii.AssetID, (sbyte)tii.Type); + } + + // FIXME: We need to make gathering modular but we cannot yet, since gatherers are not guaranteed + // to be called with scene objects that are in a scene (e.g. in the case of hg asset mapping and + // inventory transfer. There needs to be a way for a module to register a method without assuming a + // Scene.EventManager is present. + // part.ParentGroup.Scene.EventManager.TriggerGatherUuids(part, assetUuids); + + + // still needed to retrieve textures used as materials for any parts containing legacy materials stored in DynAttrs + RecordMaterialsUuids(part); + } + catch (Exception e) + { + m_log.ErrorFormat("[UUID GATHERER]: Failed to get part - {0}", e); + m_log.DebugFormat( + "[UUID GATHERER]: Texture entry length for prim was {0} (min is 46)", + part.Shape.TextureEntry.Length); + } + } + } /// /// Gathers the next set of assets returned by the next uuid to get from the asset service. @@ -804,7 +910,7 @@ namespace OpenSim.Region.Framework.Scenes } } - private void RecordAssetUuids(UUID assetUuid, sbyte assetType) + private void AddForInspection(UUID assetUuid, sbyte assetType) { // Here, we want to collect uuids which require further asset fetches but mark the others as gathered try @@ -813,27 +919,27 @@ namespace OpenSim.Region.Framework.Scenes if ((sbyte)AssetType.Bodypart == assetType || (sbyte)AssetType.Clothing == assetType) { - AddAssetUuidToInspect(assetUuid); + AddForInspection(assetUuid); } else if ((sbyte)AssetType.Gesture == assetType) { - AddAssetUuidToInspect(assetUuid); + AddForInspection(assetUuid); } else if ((sbyte)AssetType.Notecard == assetType) { - AddAssetUuidToInspect(assetUuid); + AddForInspection(assetUuid); } else if ((sbyte)AssetType.LSLText == assetType) { - AddAssetUuidToInspect(assetUuid); + AddForInspection(assetUuid); } else if ((sbyte)OpenSimAssetType.Material == assetType) { - AddAssetUuidToInspect(assetUuid); + AddForInspection(assetUuid); } else if ((sbyte)AssetType.Object == assetType) { - AddAssetUuidToInspect(assetUuid); + AddForInspection(assetUuid); } } catch (Exception) @@ -846,107 +952,6 @@ namespace OpenSim.Region.Framework.Scenes } /// - /// Gather all the asset uuids associated with a given object. - /// - /// - /// This includes both those directly associated with - /// it (e.g. face textures) and recursively, those of items within it's inventory (e.g. objects contained - /// within this object). - /// - /// The scene object for which to gather assets - public void RecordAssetUuids(SceneObjectGroup sceneObject) - { - // m_log.DebugFormat( - // "[ASSET GATHERER]: Getting assets for object {0}, {1}", sceneObject.Name, sceneObject.UUID); - - SceneObjectPart[] parts = sceneObject.Parts; - for (int i = 0; i < parts.Length; i++) - { - SceneObjectPart part = parts[i]; - - // m_log.DebugFormat( - // "[ARCHIVER]: Getting part {0}, {1} for object {2}", part.Name, part.UUID, sceneObject.UUID); - - try - { - Primitive.TextureEntry textureEntry = part.Shape.Textures; - if (textureEntry != null) - { - // Get the prim's default texture. This will be used for faces which don't have their own texture - if (textureEntry.DefaultTexture != null) - RecordTextureEntryAssetUuids(textureEntry.DefaultTexture); - - if (textureEntry.FaceTextures != null) - { - // Loop through the rest of the texture faces (a non-null face means the face is different from DefaultTexture) - foreach (Primitive.TextureEntryFace texture in textureEntry.FaceTextures) - { - if (texture != null) - RecordTextureEntryAssetUuids(texture); - } - } - } - - // If the prim is a sculpt then preserve this information too - if (part.Shape.SculptTexture != UUID.Zero) - m_gatheredAssetUuids[part.Shape.SculptTexture] = (sbyte)AssetType.Texture; - - if (part.Shape.ProjectionTextureUUID != UUID.Zero) - m_gatheredAssetUuids[part.Shape.ProjectionTextureUUID] = (sbyte)AssetType.Texture; - - if (part.CollisionSound != UUID.Zero) - m_gatheredAssetUuids[part.CollisionSound] = (sbyte)AssetType.Sound; - - if (part.ParticleSystem.Length > 0) - { - try - { - Primitive.ParticleSystem ps = new Primitive.ParticleSystem(part.ParticleSystem, 0); - if (ps.Texture != UUID.Zero) - m_gatheredAssetUuids[ps.Texture] = (sbyte)AssetType.Texture; - } - catch (Exception) - { - m_log.WarnFormat( - "[UUID GATHERER]: Could not check particle system for part {0} {1} in object {2} {3} since it is corrupt. Continuing.", - part.Name, part.UUID, sceneObject.Name, sceneObject.UUID); - } - } - - TaskInventoryDictionary taskDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone(); - - // Now analyze this prim's inventory items to preserve all the uuids that they reference - foreach (TaskInventoryItem tii in taskDictionary.Values) - { - // m_log.DebugFormat( - // "[ARCHIVER]: Analysing item {0} asset type {1} in {2} {3}", - // tii.Name, tii.Type, part.Name, part.UUID); - - if (!m_gatheredAssetUuids.ContainsKey(tii.AssetID)) - RecordAssetUuids(tii.AssetID, (sbyte)tii.Type); - } - - // FIXME: We need to make gathering modular but we cannot yet, since gatherers are not guaranteed - // to be called with scene objects that are in a scene (e.g. in the case of hg asset mapping and - // inventory transfer. There needs to be a way for a module to register a method without assuming a - // Scene.EventManager is present. - // part.ParentGroup.Scene.EventManager.TriggerGatherUuids(part, assetUuids); - - - // still needed to retrieve textures used as materials for any parts containing legacy materials stored in DynAttrs - RecordMaterialsUuids(part); - } - catch (Exception e) - { - m_log.ErrorFormat("[UUID GATHERER]: Failed to get part - {0}", e); - m_log.DebugFormat( - "[UUID GATHERER]: Texture entry length for prim was {0} (min is 46)", - part.Shape.TextureEntry.Length); - } - } - } - - /// /// Collect all the asset uuids found in one face of a Texture Entry. /// private void RecordTextureEntryAssetUuids(Primitive.TextureEntryFace texture) @@ -954,7 +959,7 @@ namespace OpenSim.Region.Framework.Scenes m_gatheredAssetUuids[texture.TextureID] = (sbyte)AssetType.Texture; if (texture.MaterialID != UUID.Zero) - AddAssetUuidToInspect(texture.MaterialID); + AddForInspection(texture.MaterialID); } /// @@ -962,7 +967,7 @@ namespace OpenSim.Region.Framework.Scenes /// stored in legacy format in part.DynAttrs /// /// - public void RecordMaterialsUuids(SceneObjectPart part) + private void RecordMaterialsUuids(SceneObjectPart part) { // scan thru the dynAttrs map of this part for any textures used as materials OSD osdMaterials = null; @@ -1053,7 +1058,7 @@ namespace OpenSim.Region.Framework.Scenes UUID uuid = new UUID(uuidMatch.Value); // m_log.DebugFormat("[ARCHIVER]: Recording {0} in text", uuid); - AddAssetUuidToInspect(uuid); + AddForInspection(uuid); } } @@ -1088,14 +1093,14 @@ namespace OpenSim.Region.Framework.Scenes if (CoalescedSceneObjectsSerializer.TryFromXml(xml, out coa)) { foreach (SceneObjectGroup sog in coa.Objects) - RecordAssetUuids(sog); + AddForInspection(sog); } else { SceneObjectGroup sog = SceneObjectSerializer.FromOriginalXmlFormat(xml); if (null != sog) - RecordAssetUuids(sog); + AddForInspection(sog); } } -- cgit v1.1 From 76722d832486b521610ee422dfa4c78a5797f3a9 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 9 Dec 2014 23:59:19 +0000 Subject: In XEngine, enqueue a script rez to the compile queue after setting m_CompileDict to avoid a rare but not impossible race condition. --- OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index 752b397..7ff82e6 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -1020,11 +1020,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine } else { - m_CompileQueue.Enqueue(parms); lock (m_CompileDict) - { m_CompileDict[itemID] = 0; - } + + // This must occur after the m_CompileDict so that an existing compile thread cannot hit the check + // in DoOnRezScript() before m_CompileDict has been updated. + m_CompileQueue.Enqueue(parms); // m_log.DebugFormat("[XEngine]: Added script {0} to compile queue", itemID); -- cgit v1.1 From 227d2e2b616ad52331b387f2dbf3392583f194f6 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 10 Dec 2014 00:04:10 +0000 Subject: Avoid a possible race condition where the XEngine script compile thread could complete but see OnRezScript() insert a new job and complete before it set m_CurrentCompile = null If the above happened, it would mean the new script would not compile until some script was added for compilation. --- OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'OpenSim') diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index 7ff82e6..ccd5d99 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -1101,7 +1101,15 @@ namespace OpenSim.Region.ScriptEngine.XEngine // due to a race condition // lock (m_CompileQueue) + { m_CurrentCompile = null; + + // This is to avoid a situation where the m_CompileQueue while loop above could complete but + // OnRezScript() place a new script on the queue and check m_CurrentCompile = null before we hit + // this section. + if (m_CompileQueue.Count > 0) + m_CurrentCompile = m_ThreadPool.QueueWorkItem(DoOnRezScriptQueue, null); + } } return null; -- cgit v1.1 From 2b9f0647de513f6a916d9d58d4e7883d30b804d3 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 10 Dec 2014 00:25:27 +0000 Subject: Fix a regression where objects crossing regions in the same simulator (on their own or as attachments) with AppDomainLoading = false would create the new state in the source region area rather than the dest. This was beause the code was finding the script DLL compiled for the source region as everything is in the same appdomain and using this as the location for the destination script state, etc. This resolves the regression by passing the proper destination separately from the DLL retrieved. Probably a regression since commit d7b92604 (11 July 2014). Added regression test for this case. At least partly addresses http://opensimulator.org/mantis/view.php?id=7278 --- OpenSim/Framework/ISceneObject.cs | 2 + .../Avatar/Attachments/AttachmentsModule.cs | 7 + .../ScriptEngine/Interfaces/IScriptInstance.cs | 2 +- .../ScriptEngine/Shared/Instance/ScriptInstance.cs | 66 +++---- .../XEngine/Tests/XEngineBasicTests.cs | 4 +- .../XEngine/Tests/XEngineCrossingTests.cs | 195 +++++++++++++++++++++ OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | 51 +++--- 7 files changed, 266 insertions(+), 61 deletions(-) create mode 100644 OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineCrossingTests.cs (limited to 'OpenSim') diff --git a/OpenSim/Framework/ISceneObject.cs b/OpenSim/Framework/ISceneObject.cs index afac9b8..754b77b 100644 --- a/OpenSim/Framework/ISceneObject.cs +++ b/OpenSim/Framework/ISceneObject.cs @@ -32,6 +32,8 @@ namespace OpenSim.Framework { public interface ISceneObject { + string Name { get; } + UUID UUID { get; } /// diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index a3368fb..ff7a062 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -255,6 +255,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments public void CopyAttachments(AgentData ad, IScenePresence sp) { +// m_log.DebugFormat("[ATTACHMENTS MODULE]: Copying attachment data into {0} in {1}", sp.Name, m_scene.Name); + if (ad.AttachmentObjects != null && ad.AttachmentObjects.Count > 0) { lock (sp.AttachmentsSyncLock) @@ -265,6 +267,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments { ((SceneObjectGroup)so).LocalId = 0; ((SceneObjectGroup)so).RootPart.ClearUpdateSchedule(); + +// m_log.DebugFormat( +// "[ATTACHMENTS MODULE]: Copying script state with {0} bytes for object {1} for {2} in {3}", +// ad.AttachmentObjectStates[i].Length, so.Name, sp.Name, m_scene.Name); + so.SetState(ad.AttachmentObjectStates[i++], m_scene); m_scene.IncomingCreateObject(Vector3.Zero, so); } diff --git a/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs b/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs index b9a217b..1097efb 100644 --- a/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs +++ b/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs @@ -222,7 +222,7 @@ namespace OpenSim.Region.ScriptEngine.Interfaces void SetVars(Dictionary vars); DetectParams GetDetectParams(int idx); UUID GetDetectID(int idx); - void SaveState(string assembly); + void SaveState(); void DestroyScriptInstance(); IScriptApi GetApi(string name); diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs index 637c556..b983be9 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs @@ -71,7 +71,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance private bool m_TimerQueued; private DateTime m_EventStart; private bool m_InEvent; - private string m_Assembly; + private string m_assemblyPath; + private string m_dataPath; private string m_CurrentEvent = String.Empty; private bool m_InSelfDelete; private int m_MaxScriptQueue; @@ -244,12 +245,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance /// /// /// + /// + /// Path for all script associated data (state, etc.). In a multi-region set up + /// with all scripts loading into the same AppDomain this may not be the same place as the DLL itself. + /// /// /// false if load failed, true if suceeded - public bool Load(AppDomain dom, Assembly scriptAssembly, StateSource stateSource) + public bool Load(AppDomain dom, Assembly scriptAssembly, string dataPath, StateSource stateSource) { - //m_Assembly = scriptAssembly.CodeBase; - m_Assembly = scriptAssembly.Location; + m_assemblyPath = scriptAssembly.Location; + m_dataPath = dataPath; m_stateSource = stateSource; try @@ -270,14 +275,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance constructorParams = null; } -// m_log.DebugFormat( -// "[SCRIP -// scriptType.FullName, m_Assembly, Engine.World.Name); - if (dom != System.AppDomain.CurrentDomain) m_Script = (IScript)dom.CreateInstanceAndUnwrap( - Path.GetFileNameWithoutExtension(m_Assembly), + Path.GetFileNameWithoutExtension(m_assemblyPath), scriptType.FullName, false, BindingFlags.Default, @@ -305,7 +306,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance { m_log.ErrorFormat( "[SCRIPT INSTANCE]: Not starting script {0} (id {1}) in part {2} (id {3}) in object {4} in {5}. Error loading assembly {6}. Exception {7}{8}", - ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name, m_Assembly, e.Message, e.StackTrace); + ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name, scriptAssembly.Location, e.Message, e.StackTrace); return false; } @@ -340,10 +341,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance m_SaveState = true; - string savedState = Path.Combine(Path.GetDirectoryName(m_Assembly), ItemID.ToString() + ".state"); + string savedState = Path.Combine(m_dataPath, ItemID.ToString() + ".state"); if (File.Exists(savedState)) { +// m_log.DebugFormat( +// "[SCRIPT INSTANCE]: Found state for script {0} for {1} ({2}) at {3} in {4}", +// ItemID, savedState, Part.Name, Part.ParentGroup.Name, Part.ParentGroup.Scene.Name); + string xml = String.Empty; try @@ -385,12 +390,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance m_startedFromSavedState = true; } } - else - { - m_log.WarnFormat( - "[SCRIPT INSTANCE]: Not starting script {0} (id {1}) in part {2} (id {3}) in object {4} in {5}. Unable to load script state file {6}. Memory limit exceeded.", - ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name, savedState); - } +// else +// { +// m_log.WarnFormat( +// "[SCRIPT INSTANCE]: Not starting script {0} (id {1}) in part {2} (id {3}) in object {4} in {5}. Unable to load script state file {6}. Memory limit exceeded.", +// ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name, savedState); +// } } catch (Exception e) { @@ -401,11 +406,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance } // else // { -// ScenePresence presence = Engine.World.GetScenePresence(part.OwnerID); - -// if (presence != null && (!postOnRez)) -// presence.ControllingClient.SendAgentAlertMessage("Compile successful", false); - +// m_log.DebugFormat( +// "[SCRIPT INSTANCE]: Did not find state for script {0} for {1} ({2}) at {3} in {4}", +// ItemID, savedState, Part.Name, Part.ParentGroup.Name, Part.ParentGroup.Scene.Name); // } return true; @@ -498,8 +501,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance public void RemoveState() { - string savedState = Path.Combine(Path.GetDirectoryName(m_Assembly), - ItemID.ToString() + ".state"); + string savedState = Path.Combine(m_dataPath, ItemID.ToString() + ".state"); + +// m_log.DebugFormat( +// "[SCRIPT INSTANCE]: Deleting state {0} for script {1} (id {2}) in part {3} (id {4}) in object {5} in {6}.", +// savedState, ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name); try { @@ -822,8 +828,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance if (Engine.World.PipeEventsForScript(LocalID) || data.EventName == "control") // Don't freeze avies! { - // m_log.DebugFormat("[Script] Delivered event {2} in state {3} to {0}.{1}", - // PrimName, ScriptName, data.EventName, State); +// m_log.DebugFormat("[Script] Delivered event {2} in state {3} to {0}.{1}", +// PrimName, ScriptName, data.EventName, State); try { @@ -849,7 +855,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance // This will be the very first event we deliver // (state_entry) in default state // - SaveState(m_Assembly); + SaveState(); m_SaveState = false; } @@ -1043,7 +1049,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance return m_DetectParams[idx].Key; } - public void SaveState(string assembly) + public void SaveState() { // If we're currently in an event, just tell it to save upon return // @@ -1065,7 +1071,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance { try { - using (FileStream fs = File.Create(Path.Combine(Path.GetDirectoryName(assembly), ItemID.ToString() + ".state"))) + using (FileStream fs = File.Create(Path.Combine(m_dataPath, ItemID.ToString() + ".state"))) { Byte[] buf = Util.UTF8NoBomEncoding.GetBytes(xml); fs.Write(buf, 0, buf.Length); @@ -1149,7 +1155,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance public string GetAssemblyName() { - return m_Assembly; + return m_assemblyPath; } public string GetXMLState() diff --git a/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineBasicTests.cs b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineBasicTests.cs index fe15157..878e571 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineBasicTests.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineBasicTests.cs @@ -40,10 +40,10 @@ using OpenSim.Tests.Common; namespace OpenSim.Region.ScriptEngine.XEngine.Tests { /// - /// XEngine tests. + /// Basic XEngine tests. /// [TestFixture] - public class XEngineTest : OpenSimTestCase + public class XEngineBasicTests : OpenSimTestCase { private TestScene m_scene; private XEngine m_xEngine; diff --git a/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineCrossingTests.cs b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineCrossingTests.cs new file mode 100644 index 0000000..587695f --- /dev/null +++ b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineCrossingTests.cs @@ -0,0 +1,195 @@ +/* + * 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.Threading; +using Nini.Config; +using NUnit.Framework; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Region.CoreModules.Framework.EntityTransfer; +using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.ScriptEngine.Shared; +using OpenSim.Tests.Common; + +namespace OpenSim.Region.ScriptEngine.XEngine.Tests +{ + /// + /// XEngine tests connected with crossing scripts between regions. + /// + [TestFixture] + public class XEngineCrossingTests : OpenSimTestCase + { + [TestFixtureSetUp] + public void FixtureInit() + { + // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread. + Util.FireAndForgetMethod = FireAndForgetMethod.RegressionTest; + } + + [TestFixtureTearDown] + public void TearDown() + { + // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple + // threads. Possibly, later tests should be rewritten so none of them require async stuff (which regression + // tests really shouldn't). + Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod; + } + + /// + /// Test script state preservation when a script crosses between regions on the same simulator. + /// + [Test] + public void TestScriptCrossOnSameSimulator() + { + TestHelpers.InMethod(); +// TestHelpers.EnableLogging(); + + UUID userId = TestHelpers.ParseTail(0x1); + int sceneObjectIdTail = 0x2; + + EntityTransferModule etmA = new EntityTransferModule(); + EntityTransferModule etmB = new EntityTransferModule(); + LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule(); + XEngine xEngineA = new XEngine(); + XEngine xEngineB = new XEngine(); + xEngineA.DebugLevel = 1; + xEngineB.DebugLevel = 1; + + IConfigSource configSource = new IniConfigSource(); + + IConfig startupConfig = configSource.AddConfig("Startup"); + startupConfig.Set("DefaultScriptEngine", "XEngine"); + + IConfig xEngineConfig = configSource.AddConfig("XEngine"); + xEngineConfig.Set("Enabled", "true"); + xEngineConfig.Set("StartDelay", "0"); + + // These tests will not run with AppDomainLoading = true, at least on mono. For unknown reasons, the call + // to AssemblyResolver.OnAssemblyResolve fails. + xEngineConfig.Set("AppDomainLoading", "false"); + + IConfig modulesConfig = configSource.AddConfig("Modules"); + modulesConfig.Set("EntityTransferModule", etmA.Name); + modulesConfig.Set("SimulationServices", lscm.Name); + + SceneHelpers sh = new SceneHelpers(); + TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000, configSource); + TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1000, 999, configSource); + + SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, configSource, lscm); + SceneHelpers.SetupSceneModules(sceneA, configSource, etmA, xEngineA); + SceneHelpers.SetupSceneModules(sceneB, configSource, etmB, xEngineB); + sceneA.StartScripts(); + sceneB.StartScripts(); + + SceneObjectGroup soSceneA = SceneHelpers.AddSceneObject(sceneA, 1, userId, "so1-", sceneObjectIdTail); + soSceneA.AbsolutePosition = new Vector3(128, 10, 20); + + // CREATE SCRIPT TODO + InventoryItemBase scriptItemSceneA = new InventoryItemBase(); + // itemTemplate.ID = itemId; + scriptItemSceneA.Name = "script1"; + scriptItemSceneA.Folder = soSceneA.UUID; + scriptItemSceneA.InvType = (int)InventoryType.LSL; + + AutoResetEvent chatEvent = new AutoResetEvent(false); + OSChatMessage messageReceived = null; + sceneA.EventManager.OnChatFromWorld += (s, m) => { messageReceived = m; chatEvent.Set(); }; + + sceneA.RezNewScript(userId, scriptItemSceneA, +@"integer c = 0; + +default +{ + state_entry() + { + llSay(0, ""Script running""); + } + + changed(integer change) + { + llSay(0, ""Changed""); + } + + touch_start(integer n) + { + c = c + 1; + llSay(0, (string)c); + } +}"); + + chatEvent.WaitOne(60000); + + Assert.That(messageReceived, Is.Not.Null, "No chat message received."); + Assert.That(messageReceived.Message, Is.EqualTo("Script running")); + + { + // XXX: Should not be doing this so directly. Should call some variant of EventManager.touch() instead. + DetectParams[] det = new DetectParams[1]; + det[0] = new DetectParams(); + det[0].Key = userId; + det[0].Populate(sceneA); + + EventParams ep = new EventParams("touch_start", new Object[] { new LSL_Types.LSLInteger(1) }, det); + + xEngineA.PostObjectEvent(soSceneA.LocalId, ep); + chatEvent.WaitOne(60000); + + Assert.That(messageReceived.Message, Is.EqualTo("1")); + } + + sceneB.EventManager.OnChatFromWorld += (s, m) => { messageReceived = m; chatEvent.Set(); }; + + // Cross with a negative value + soSceneA.AbsolutePosition = new Vector3(128, -10, 20); + + chatEvent.WaitOne(60000); + Assert.That(messageReceived.Message, Is.EqualTo("Changed")); + + // TEST sending event to moved prim and output + { + SceneObjectGroup soSceneB = sceneB.GetSceneObjectGroup(soSceneA.Name); + TaskInventoryItem scriptItemSceneB = soSceneB.RootPart.Inventory.GetInventoryItem(scriptItemSceneA.Name); + + // XXX: Should not be doing this so directly. Should call some variant of EventManager.touch() instead. + DetectParams[] det = new DetectParams[1]; + det[0] = new DetectParams(); + det[0].Key = userId; + det[0].Populate(sceneB); + + EventParams ep = new EventParams("touch_start", new Object[] { new LSL_Types.LSLInteger(1) }, det); + + xEngineB.PostObjectEvent(soSceneB.LocalId, ep); + chatEvent.WaitOne(60000); + + Assert.That(messageReceived.Message, Is.EqualTo("2")); + } + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index ccd5d99..71ed989 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -716,22 +716,17 @@ namespace OpenSim.Region.ScriptEngine.XEngine { // Force a final state save // - if (m_Assemblies.ContainsKey(instance.AssetID)) + try { - string assembly = m_Assemblies[instance.AssetID]; - - try - { - instance.SaveState(assembly); - } - catch (Exception e) - { - m_log.Error( - string.Format( - "[XEngine]: Failed final state save for script {0}.{1}, item UUID {2}, prim UUID {3} in {4}. Exception ", - instance.PrimName, instance.ScriptName, instance.ItemID, instance.ObjectID, World.Name) - , e); - } + instance.SaveState(); + } + catch (Exception e) + { + m_log.Error( + string.Format( + "[XEngine]: Failed final state save for script {0}.{1}, item UUID {2}, prim UUID {3} in {4}. Exception ", + instance.PrimName, instance.ScriptName, instance.ItemID, instance.ObjectID, World.Name) + , e); } // Clear the event queue and abort the instance thread @@ -840,18 +835,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine foreach (IScriptInstance i in instances) { - string assembly = String.Empty; - - lock (m_Scripts) - { - if (!m_Assemblies.ContainsKey(i.AssetID)) - continue; - assembly = m_Assemblies[i.AssetID]; - } - try { - i.SaveState(assembly); + i.SaveState(); } catch (Exception e) { @@ -1180,7 +1166,11 @@ namespace OpenSim.Region.ScriptEngine.XEngine lock (m_AddingAssemblies) { m_Compiler.PerformScriptCompile(script, assetID.ToString(), item.OwnerID, out assemblyPath, out linemap); - + +// m_log.DebugFormat( +// "[XENGINE]: Found assembly path {0} onrez {1} in {2}", +// assemblyPath, item.ItemID, World.Name); + if (!m_AddingAssemblies.ContainsKey(assemblyPath)) { m_AddingAssemblies[assemblyPath] = 1; } else { @@ -1373,7 +1363,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine startParam, postOnRez, m_MaxScriptQueue); - if (!instance.Load(m_AppDomains[appDomain], scriptAssembly, stateSource)) + if (!instance.Load( + m_AppDomains[appDomain], scriptAssembly, + Path.Combine(ScriptEnginePath, World.RegionInfo.RegionID.ToString()), stateSource)) return false; // if (DebugLevel >= 1) @@ -1604,7 +1596,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine IScriptInstance instance = (ScriptInstance) parms; - //m_log.DebugFormat("[XEngine]: Processing event for {0}", instance); +// m_log.DebugFormat("[XEngine]: Processing event for {0}", instance); return instance.EventProcessor(); } @@ -2200,6 +2192,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine m_log.ErrorFormat("[XEngine]: Error whilst writing state file {0}, {1}", statepath, ex.Message); } +// m_log.DebugFormat( +// "[XEngine]: Wrote state for script item with ID {0} at {1} in {2}", itemID, statepath, m_Scene.Name); + return true; } -- cgit v1.1 From 147d401b28d6a0193122ec6518e9aaf9d22da816 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 15 Dec 2014 20:38:26 +0000 Subject: Remove XEngine.m_uniqueScripts This provides no obvious benefit as far as I can tell but has a definite cost in keep script strings in memory for the entire simulator session. --- OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | 8 -------- 1 file changed, 8 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index 71ed989..906c6ee 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -101,7 +101,6 @@ namespace OpenSim.Region.ScriptEngine.XEngine private bool m_InitialStartup = true; private int m_ScriptFailCount; // Number of script fails since compile queue was last empty private string m_ScriptErrorMessage; - private Dictionary m_uniqueScripts = new Dictionary(); private bool m_AppDomainLoading; private Dictionary m_ScriptErrors = new Dictionary(); @@ -570,7 +569,6 @@ namespace OpenSim.Region.ScriptEngine.XEngine } sb.AppendFormat("Scripts loaded : {0}\n", scriptsLoaded); - sb.AppendFormat("Unique scripts : {0}\n", m_uniqueScripts.Count); sb.AppendFormat("Scripts waiting for load : {0}\n", m_CompileQueue.Count); sb.AppendFormat("Max threads : {0}\n", m_ThreadPool.MaxThreads); sb.AppendFormat("Min threads : {0}\n", m_ThreadPool.MinThreads); @@ -987,12 +985,6 @@ namespace OpenSim.Region.ScriptEngine.XEngine if (engine != ScriptEngineName) return; - // If we've seen this exact script text before, use that reference instead - if (m_uniqueScripts.ContainsKey(script)) - script = m_uniqueScripts[script]; - else - m_uniqueScripts[script] = script; - Object[] parms = new Object[]{localID, itemID, script, startParam, postOnRez, (StateSource)stateSource}; if (stateSource == (int)StateSource.ScriptedRez) -- cgit v1.1 From b39d697555794e3398c92ccebb92c6280bdbee9f Mon Sep 17 00:00:00 2001 From: BlueWall Date: Tue, 16 Dec 2014 12:20:56 -0500 Subject: Adding command to reset user's email address --- .../UserAccountService/UserAccountService.cs | 44 +++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) (limited to 'OpenSim') diff --git a/OpenSim/Services/UserAccountService/UserAccountService.cs b/OpenSim/Services/UserAccountService/UserAccountService.cs index ec6118b..4705445 100644 --- a/OpenSim/Services/UserAccountService/UserAccountService.cs +++ b/OpenSim/Services/UserAccountService/UserAccountService.cs @@ -98,7 +98,12 @@ namespace OpenSim.Services.UserAccountService MainConsole.Instance.Commands.AddCommand("Users", false, "reset user password", "reset user password [ [ []]]", - "Reset a user password", HandleResetUserPassword); + "Reset a user password", HandleResetUserPassword); + + MainConsole.Instance.Commands.AddCommand("Users", false, + "reset user email", + "reset user email [ [ []]]", + "Reset a user email address", HandleResetUserEmail); MainConsole.Instance.Commands.AddCommand("Users", false, "set user level", @@ -420,6 +425,43 @@ namespace OpenSim.Services.UserAccountService MainConsole.Instance.OutputFormat("Password reset for user {0} {1}", firstName, lastName); } + protected void HandleResetUserEmail(string module, string[] cmdparams) + { + string firstName; + string lastName; + string newEmail; + + if (cmdparams.Length < 4) + firstName = MainConsole.Instance.CmdPrompt("First name"); + else firstName = cmdparams[3]; + + if (cmdparams.Length < 5) + lastName = MainConsole.Instance.CmdPrompt("Last name"); + else lastName = cmdparams[4]; + + if (cmdparams.Length < 6) + newEmail = MainConsole.Instance.PasswdPrompt("New Email"); + else newEmail = cmdparams[5]; + + UserAccount account = GetUserAccount(UUID.Zero, firstName, lastName); + if (account == null) + { + MainConsole.Instance.OutputFormat("No such user as {0} {1}", firstName, lastName); + return; + } + + bool success = false; + + account.Email = newEmail; + + success = StoreUserAccount(account); + if (!success) + MainConsole.Instance.OutputFormat("Unable to set Email for account {0} {1}.", firstName, lastName); + else + MainConsole.Instance.OutputFormat("User Email set for user {0} {1} to {2}", firstName, lastName, account.Email); + } + + protected void HandleSetUserLevel(string module, string[] cmdparams) { string firstName; -- cgit v1.1 From e50aac020f6a0b522b507cb3fac930103203dbc8 Mon Sep 17 00:00:00 2001 From: BlueWall Date: Tue, 16 Dec 2014 12:47:02 -0500 Subject: Add command to reset region's user cache --- .../Framework/UserManagement/UserManagementModule.cs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs index 9bf7885..6479430 100644 --- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs +++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs @@ -680,6 +680,21 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement "Show the bindings between user UUIDs and user names", String.Empty, HandleShowUsers); + + MainConsole.Instance.Commands.AddCommand("Users", true, + "reset user cache", + "reset user cache", + "reset user cache to allow changed settings to be applied", + String.Empty, + HandleResetUserCache); + } + + private void HandleResetUserCache(string module, string[] cmd) + { + lock(m_UserCache) + { + m_UserCache.Clear(); + } } private void HandleShowUser(string module, string[] cmd) -- cgit v1.1 From e901253b49668f1e1d8f135f2d05aaec7baad40a Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 17 Dec 2014 00:21:58 +0000 Subject: Fix recent regression where a race condition meant SP.MakeRootAgent() would sometimes look to start attachment scripts before ETM.HandleIncomingSceneObject() had added them. Probably a regression since ghosts branch merge on Nov 26 2014 --- .../Avatar/Attachments/AttachmentsModule.cs | 16 ++++-- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 61 ++++++++++------------ 2 files changed, 40 insertions(+), 37 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index ff7a062..4af4ddb 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -341,11 +341,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments if (!Enabled) return; - if (DebugLevel > 0) - m_log.DebugFormat("[ATTACHMENTS MODULE]: Saving changed attachments for {0}", sp.Name); - List attachments = sp.GetAttachments(); + if (DebugLevel > 0) + m_log.DebugFormat( + "[ATTACHMENTS MODULE]: Saving for {0} attachments for {1} in {2}", + attachments.Count, sp.Name, m_scene.Name); + if (attachments.Count <= 0) return; @@ -359,6 +361,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments // This must be done outside the sp.AttachmentSyncLock so that there is no risk of a deadlock from // scripts performing attachment operations at the same time. Getting object states stops the scripts. scriptStates[so] = PrepareScriptInstanceForSave(so, false); + +// m_log.DebugFormat( +// "[ATTACHMENTS MODULE]: For object {0} for {1} in {2} got saved state {3}", +// so.Name, sp.Name, m_scene.Name, scriptStates[so]); } lock (sp.AttachmentsSyncLock) @@ -826,8 +832,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments { if (DebugLevel > 0) m_log.DebugFormat( - "[ATTACHMENTS MODULE]: Adding attachment {0} to avatar {1} in pt {2} pos {3} {4}", - so.Name, sp.Name, attachmentpoint, attachOffset, so.RootPart.AttachedPos); + "[ATTACHMENTS MODULE]: Adding attachment {0} to avatar {1} at pt {2} pos {3} {4} in {5}", + so.Name, sp.Name, attachmentpoint, attachOffset, so.RootPart.AttachedPos, m_scene.Name); // Remove from database and parcel prim count m_scene.DeleteFromStorage(so.UUID); diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 93dfd00..0414f89 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -1228,45 +1228,27 @@ namespace OpenSim.Region.Framework.Scenes m_scene.SwapRootAgentCount(false); - // The initial login scene presence is already root when it gets here - // and it has already rezzed the attachments and started their scripts. - // We do the following only for non-login agents, because their scripts - // haven't started yet. - if (PresenceType == PresenceType.Npc || IsRealLogin(m_teleportFlags)) - { - // Viewers which have a current outfit folder will actually rez their own attachments. However, - // viewers without (e.g. v1 viewers) will not, so we still need to make this call. - if (Scene.AttachmentsModule != null) + if (Scene.AttachmentsModule != null) + { + // The initial login scene presence is already root when it gets here + // and it has already rezzed the attachments and started their scripts. + // We do the following only for non-login agents, because their scripts + // haven't started yet. + if (PresenceType == PresenceType.Npc || IsRealLogin(m_teleportFlags)) { + // Viewers which have a current outfit folder will actually rez their own attachments. However, + // viewers without (e.g. v1 viewers) will not, so we still need to make this call. WorkManager.RunJob( "RezAttachments", o => Scene.AttachmentsModule.RezAttachments(this), null, string.Format("Rez attachments for {0} in {1}", Name, Scene.Name)); } - } - else - { - // We need to restart scripts here so that they receive the correct changed events (CHANGED_TELEPORT - // and CHANGED_REGION) when the attachments have been rezzed in the new region. This cannot currently - // be done in AttachmentsModule.CopyAttachments(AgentData ad, IScenePresence sp) itself since we are - // not transporting the required data. - // - // We must take a copy of the attachments list here (rather than locking) to avoid a deadlock where a script in one of - // the attachments may start processing an event (which locks ScriptInstance.m_Script) that then calls a method here - // which needs to lock m_attachments. ResumeScripts() needs to take a ScriptInstance.m_Script lock to try to unset the Suspend status. - // - // FIXME: In theory, this deadlock should not arise since scripts should not be processing events until ResumeScripts(). - // But XEngine starts all scripts unsuspended. Starting them suspended will not currently work because script rezzing - // is placed in an asynchronous queue in XEngine and so the ResumeScripts() call will almost certainly execute before the - // script is rezzed. This means the ResumeScripts() does absolutely nothing when using XEngine. - List attachments = GetAttachments(); - - if (attachments.Count > 0) + else { WorkManager.RunJob( - "StartAttachmentScripts", - o => RestartAttachmentScripts(attachments), + "StartAttachmentScripts", + o => RestartAttachmentScripts(), null, string.Format("Start attachment scripts for {0} in {1}", Name, Scene.Name), true); @@ -1292,10 +1274,25 @@ namespace OpenSim.Region.Framework.Scenes return true; } - private void RestartAttachmentScripts(List attachments) + private void RestartAttachmentScripts() { + // We need to restart scripts here so that they receive the correct changed events (CHANGED_TELEPORT + // and CHANGED_REGION) when the attachments have been rezzed in the new region. This cannot currently + // be done in AttachmentsModule.CopyAttachments(AgentData ad, IScenePresence sp) itself since we are + // not transporting the required data. + // + // We must take a copy of the attachments list here (rather than locking) to avoid a deadlock where a script in one of + // the attachments may start processing an event (which locks ScriptInstance.m_Script) that then calls a method here + // which needs to lock m_attachments. ResumeScripts() needs to take a ScriptInstance.m_Script lock to try to unset the Suspend status. + // + // FIXME: In theory, this deadlock should not arise since scripts should not be processing events until ResumeScripts(). + // But XEngine starts all scripts unsuspended. Starting them suspended will not currently work because script rezzing + // is placed in an asynchronous queue in XEngine and so the ResumeScripts() call will almost certainly execute before the + // script is rezzed. This means the ResumeScripts() does absolutely nothing when using XEngine. + List attachments = GetAttachments(); + m_log.DebugFormat( - "[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name); + "[SCENE PRESENCE]: Restarting scripts in {0} attachments for {1} in {2}", attachments.Count, Name, Scene.Name); // Resume scripts foreach (SceneObjectGroup sog in attachments) -- cgit v1.1 From 9edc5cac96eaf65eb0dac0f3697f01f9a5c02055 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 20 Dec 2014 01:32:49 +0000 Subject: In XBakes use proper disposal semantics to always close the stream on Store() no matter what --- OpenSim/Server/Handlers/BakedTextures/XBakes.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Server/Handlers/BakedTextures/XBakes.cs b/OpenSim/Server/Handlers/BakedTextures/XBakes.cs index d1b2e12..4e55433 100644 --- a/OpenSim/Server/Handlers/BakedTextures/XBakes.cs +++ b/OpenSim/Server/Handlers/BakedTextures/XBakes.cs @@ -107,11 +107,9 @@ namespace OpenSim.Server.Handlers.BakedTextures File.Delete(diskFile); byte[] data = utf8encoding.GetBytes(sdata); - FileStream fs = File.Create(diskFile); - fs.Write(data, 0, data.Length); - - fs.Close(); + using (FileStream fs = File.Create(diskFile)) + fs.Write(data, 0, data.Length); } private void HandleDeleteBakes(string module, string[] args) -- cgit v1.1 From 798074c66f59eeeba7fbda52fcbf63f7a56c14c1 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 20 Dec 2014 01:38:48 +0000 Subject: Use using() semantics in XBakesModule to ensure disposable objects are alway disposed no matter what --- .../Avatar/BakedTextures/XBakesModule.cs | 81 +++++++++++----------- 1 file changed, 42 insertions(+), 39 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/Avatar/BakedTextures/XBakesModule.cs b/OpenSim/Region/CoreModules/Avatar/BakedTextures/XBakesModule.cs index 5e35135..c6c54b2 100644 --- a/OpenSim/Region/CoreModules/Avatar/BakedTextures/XBakesModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/BakedTextures/XBakesModule.cs @@ -112,33 +112,32 @@ namespace OpenSim.Region.CoreModules.Avatar.BakedTextures try { - Stream s = rc.Request(m_Auth); - XmlTextReader sr = new XmlTextReader(s); - - sr.ReadStartElement("BakedAppearance"); - while (sr.LocalName == "BakedTexture") + using (Stream s = rc.Request(m_Auth)) + using (XmlTextReader sr = new XmlTextReader(s)) { - string sTextureIndex = sr.GetAttribute("TextureIndex"); - int lTextureIndex = Convert.ToInt32(sTextureIndex); - string sCacheId = sr.GetAttribute("CacheId"); - UUID lCacheId = UUID.Zero; - if (!(UUID.TryParse(sCacheId, out lCacheId))) + sr.ReadStartElement("BakedAppearance"); + while (sr.LocalName == "BakedTexture") { - // ?? Nothing here + string sTextureIndex = sr.GetAttribute("TextureIndex"); + int lTextureIndex = Convert.ToInt32(sTextureIndex); + string sCacheId = sr.GetAttribute("CacheId"); + UUID lCacheId = UUID.Zero; + if (!(UUID.TryParse(sCacheId, out lCacheId))) + { + // ?? Nothing here + } + + ++size; + + sr.ReadStartElement("BakedTexture"); + AssetBase a = (AssetBase)m_serializer.Deserialize(sr); + ret.Add(new WearableCacheItem() { CacheId = lCacheId, TextureIndex = (uint)lTextureIndex, TextureAsset = a, TextureID = a.FullID }); + + sr.ReadEndElement(); } - ++size; - - sr.ReadStartElement("BakedTexture"); - AssetBase a = (AssetBase)m_serializer.Deserialize(sr); - ret.Add(new WearableCacheItem() { CacheId = lCacheId, TextureIndex = (uint)lTextureIndex, TextureAsset = a, TextureID = a.FullID }); - - sr.ReadEndElement(); + m_log.DebugFormat("[XBakes]: read {0} textures for user {1}", ret.Count, id); } - m_log.DebugFormat("[XBakes]: read {0} textures for user {1}", ret.Count, id); - sr.Close(); - s.Close(); - return ret.ToArray(); } @@ -153,27 +152,32 @@ namespace OpenSim.Region.CoreModules.Avatar.BakedTextures if (m_URL == String.Empty) return; - MemoryStream bakeStream = new MemoryStream(); - XmlTextWriter bakeWriter = new XmlTextWriter(bakeStream, null); - - bakeWriter.WriteStartElement(String.Empty, "BakedAppearance", String.Empty); + MemoryStream reqStream; - for (int i = 0; i < data.Length; i++) + using (MemoryStream bakeStream = new MemoryStream()) + using (XmlTextWriter bakeWriter = new XmlTextWriter(bakeStream, null)) { - if (data[i] != null) + bakeWriter.WriteStartElement(String.Empty, "BakedAppearance", String.Empty); + + for (int i = 0; i < data.Length; i++) { - bakeWriter.WriteStartElement(String.Empty, "BakedTexture", String.Empty); - bakeWriter.WriteAttributeString(String.Empty, "TextureIndex", String.Empty, data[i].TextureIndex.ToString()); - bakeWriter.WriteAttributeString(String.Empty, "CacheId", String.Empty, data[i].CacheId.ToString()); - if (data[i].TextureAsset != null) - m_serializer.Serialize(bakeWriter, data[i].TextureAsset); + if (data[i] != null) + { + bakeWriter.WriteStartElement(String.Empty, "BakedTexture", String.Empty); + bakeWriter.WriteAttributeString(String.Empty, "TextureIndex", String.Empty, data[i].TextureIndex.ToString()); + bakeWriter.WriteAttributeString(String.Empty, "CacheId", String.Empty, data[i].CacheId.ToString()); + if (data[i].TextureAsset != null) + m_serializer.Serialize(bakeWriter, data[i].TextureAsset); - bakeWriter.WriteEndElement(); + bakeWriter.WriteEndElement(); + } } - } - bakeWriter.WriteEndElement(); - bakeWriter.Flush(); + bakeWriter.WriteEndElement(); + bakeWriter.Flush(); + + reqStream = new MemoryStream(bakeStream.ToArray()); + } RestClient rc = new RestClient(m_URL); rc.AddResourcePath("bakes"); @@ -181,7 +185,6 @@ namespace OpenSim.Region.CoreModules.Avatar.BakedTextures rc.RequestMethod = "POST"; - MemoryStream reqStream = new MemoryStream(bakeStream.ToArray()); Util.FireAndForget( delegate { @@ -191,4 +194,4 @@ namespace OpenSim.Region.CoreModules.Avatar.BakedTextures ); } } -} +} \ No newline at end of file -- cgit v1.1 From e3d07bd0cc120e2187389f6aa4a78b0506b04f92 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 20 Dec 2014 01:39:31 +0000 Subject: minor: Correct propery doc RestClient._resource spelling mistake --- OpenSim/Framework/Communications/RestClient.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim') diff --git a/OpenSim/Framework/Communications/RestClient.cs b/OpenSim/Framework/Communications/RestClient.cs index 72018e4..4a8301e 100644 --- a/OpenSim/Framework/Communications/RestClient.cs +++ b/OpenSim/Framework/Communications/RestClient.cs @@ -90,7 +90,7 @@ namespace OpenSim.Framework.Communications private byte[] _readbuf; /// - /// MemoryStream representing the resultiong resource + /// MemoryStream representing the resulting resource /// private Stream _resource; -- cgit v1.1 From 9cff0bbd7c2d1743c252af000a712f4735f3141d Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 20 Dec 2014 01:46:32 +0000 Subject: In XBakesModule.Get() use using() to always dispose of RestClient which disposes the stream rather than disposing the stream directly --- .../Avatar/BakedTextures/XBakesModule.cs | 66 ++++++++++++---------- 1 file changed, 35 insertions(+), 31 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/Avatar/BakedTextures/XBakesModule.cs b/OpenSim/Region/CoreModules/Avatar/BakedTextures/XBakesModule.cs index c6c54b2..7d2cad6 100644 --- a/OpenSim/Region/CoreModules/Avatar/BakedTextures/XBakesModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/BakedTextures/XBakesModule.cs @@ -103,47 +103,51 @@ namespace OpenSim.Region.CoreModules.Avatar.BakedTextures return null; int size = 0; - RestClient rc = new RestClient(m_URL); - List ret = new List(); - rc.AddResourcePath("bakes"); - rc.AddResourcePath(id.ToString()); - rc.RequestMethod = "GET"; - - try + using (RestClient rc = new RestClient(m_URL)) { - using (Stream s = rc.Request(m_Auth)) - using (XmlTextReader sr = new XmlTextReader(s)) + List ret = new List(); + rc.AddResourcePath("bakes"); + rc.AddResourcePath(id.ToString()); + + rc.RequestMethod = "GET"; + + try { - sr.ReadStartElement("BakedAppearance"); - while (sr.LocalName == "BakedTexture") + Stream s = rc.Request(m_Auth); + + using (XmlTextReader sr = new XmlTextReader(s)) { - string sTextureIndex = sr.GetAttribute("TextureIndex"); - int lTextureIndex = Convert.ToInt32(sTextureIndex); - string sCacheId = sr.GetAttribute("CacheId"); - UUID lCacheId = UUID.Zero; - if (!(UUID.TryParse(sCacheId, out lCacheId))) + sr.ReadStartElement("BakedAppearance"); + while (sr.LocalName == "BakedTexture") { - // ?? Nothing here + string sTextureIndex = sr.GetAttribute("TextureIndex"); + int lTextureIndex = Convert.ToInt32(sTextureIndex); + string sCacheId = sr.GetAttribute("CacheId"); + UUID lCacheId = UUID.Zero; + if (!(UUID.TryParse(sCacheId, out lCacheId))) + { + // ?? Nothing here + } + + ++size; + + sr.ReadStartElement("BakedTexture"); + AssetBase a = (AssetBase)m_serializer.Deserialize(sr); + ret.Add(new WearableCacheItem() { CacheId = lCacheId, TextureIndex = (uint)lTextureIndex, TextureAsset = a, TextureID = a.FullID }); + + sr.ReadEndElement(); } - ++size; - - sr.ReadStartElement("BakedTexture"); - AssetBase a = (AssetBase)m_serializer.Deserialize(sr); - ret.Add(new WearableCacheItem() { CacheId = lCacheId, TextureIndex = (uint)lTextureIndex, TextureAsset = a, TextureID = a.FullID }); - - sr.ReadEndElement(); + m_log.DebugFormat("[XBakes]: read {0} textures for user {1}", ret.Count, id); } - m_log.DebugFormat("[XBakes]: read {0} textures for user {1}", ret.Count, id); + return ret.ToArray(); + } + catch (XmlException) + { + return null; } - - return ret.ToArray(); - } - catch (XmlException) - { - return null; } } -- cgit v1.1 From 7100475b90a097a3a1775d2b92756e1260383c73 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 20 Dec 2014 01:56:33 +0000 Subject: Make sure we always dispose of disposables inside RestClient.Request() --- OpenSim/Framework/Communications/RestClient.cs | 56 ++++++++++++++------------ 1 file changed, 30 insertions(+), 26 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Framework/Communications/RestClient.cs b/OpenSim/Framework/Communications/RestClient.cs index 4a8301e..6f517b6 100644 --- a/OpenSim/Framework/Communications/RestClient.cs +++ b/OpenSim/Framework/Communications/RestClient.cs @@ -352,42 +352,46 @@ namespace OpenSim.Framework.Communications m_log.DebugFormat("[LOGHTTP]: HTTP OUT {0} REST {1} to {2}", reqnum, _request.Method, _request.RequestUri); // IAsyncResult responseAsyncResult = _request.BeginGetResponse(new AsyncCallback(ResponseIsReadyDelegate), _request); + try { - _response = (HttpWebResponse) _request.GetResponse(); + using (_response = (HttpWebResponse) _request.GetResponse()) + { + using (Stream src = _response.GetResponseStream()) + { + int length = src.Read(_readbuf, 0, BufferSize); + while (length > 0) + { + _resource.Write(_readbuf, 0, length); + length = src.Read(_readbuf, 0, BufferSize); + } + + // TODO! Implement timeout, without killing the server + // this line implements the timeout, if there is a timeout, the callback fires and the request becomes aborted + //ThreadPool.RegisterWaitForSingleObject(responseAsyncResult.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), _request, DefaultTimeout, true); + + // _allDone.WaitOne(); + } + } } catch (WebException e) { - HttpWebResponse errorResponse = e.Response as HttpWebResponse; - if (null != errorResponse && HttpStatusCode.NotFound == errorResponse.StatusCode) - { - // This is often benign. E.g., requesting a missing asset will return 404. - m_log.DebugFormat("[REST CLIENT] Resource not found (404): {0}", _request.Address.ToString()); - } - else + using (HttpWebResponse errorResponse = e.Response as HttpWebResponse) { - m_log.Error(string.Format("[REST CLIENT] Error fetching resource from server: {0} ", _request.Address.ToString()), e); + if (null != errorResponse && HttpStatusCode.NotFound == errorResponse.StatusCode) + { + // This is often benign. E.g., requesting a missing asset will return 404. + m_log.DebugFormat("[REST CLIENT] Resource not found (404): {0}", _request.Address.ToString()); + } + else + { + m_log.Error(string.Format("[REST CLIENT] Error fetching resource from server: {0} ", _request.Address.ToString()), e); + } } return null; } - Stream src = _response.GetResponseStream(); - int length = src.Read(_readbuf, 0, BufferSize); - while (length > 0) - { - _resource.Write(_readbuf, 0, length); - length = src.Read(_readbuf, 0, BufferSize); - } - - - // TODO! Implement timeout, without killing the server - // this line implements the timeout, if there is a timeout, the callback fires and the request becomes aborted - //ThreadPool.RegisterWaitForSingleObject(responseAsyncResult.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), _request, DefaultTimeout, true); - -// _allDone.WaitOne(); - if (_response != null) - _response.Close(); if (_asyncException != null) throw _asyncException; @@ -515,4 +519,4 @@ namespace OpenSim.Framework.Communications #endregion Async Invocation } -} +} \ No newline at end of file -- cgit v1.1 From fc940ab09a31b27c4069e7000dbf4a75ce58c962 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 23 Dec 2014 20:38:20 +0000 Subject: If a moap entry has EnableWhiteList but WhiteList == null, then properly block the request instead of throwing an exception. Normally, WhiteList is an empty list but from Mantis 7389 it looks like it might sometimes be possible for it to be null (haven't seen this up till now) It looks like failing with an exception instead of properly replying to the request (which comes in via a cap) might be enough, surprisingly, to freeze a viewer until timeout. Part of http://opensimulator.org/mantis/view.php?id=7389 but probably unrelated to the actual issue of that mantis. --- OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs | 3 +++ 1 file changed, 3 insertions(+) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs b/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs index 601e81e..46b0470 100644 --- a/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs +++ b/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs @@ -595,6 +595,9 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap /// true if the url matches an entry on the whitelist, false otherwise protected bool CheckUrlAgainstWhitelist(string rawUrl, string[] whitelist) { + if (whitelist == null) + return false; + Uri url = new Uri(rawUrl); foreach (string origWlUrl in whitelist) -- cgit v1.1