From 02f3b116c6531f89314be6bc58115537147e512b Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 15 May 2012 22:43:47 +0100 Subject: Allow use of regular expressions in "show object name", "show part name" and "delete object name" console commands if --regex switch is used. Deleteing objects by name, creator uuid or owner uuid now requires confirmation to avoid accidental deletion. --- .../World/Objects/Commands/ObjectCommandsModule.cs | 309 ++++++++++++++------- 1 file changed, 208 insertions(+), 101 deletions(-) (limited to 'OpenSim/Region/CoreModules') diff --git a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs index 5e928f3..830d9cb 100644 --- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs +++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs @@ -29,8 +29,10 @@ using System; using System.Collections.Generic; using System.Reflection; using System.Text; +using System.Text.RegularExpressions; using log4net; using Mono.Addins; +using NDesk.Options; using Nini.Config; using OpenMetaverse; using OpenSim.Framework; @@ -78,25 +80,31 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands m_scene = scene; m_console = MainConsole.Instance; - m_console.Commands.AddCommand("Objects", false, "delete object owner", - "delete object owner ", - "Delete a scene object by owner", HandleDeleteObject); + m_console.Commands.AddCommand( + "Objects", false, "delete object owner", + "delete object owner ", + "Delete a scene object by owner", HandleDeleteObject); - m_console.Commands.AddCommand("Objects", false, "delete object creator", - "delete object creator ", - "Delete a scene object by creator", HandleDeleteObject); + m_console.Commands.AddCommand( + "Objects", false, "delete object creator", + "delete object creator ", + "Delete a scene object by creator", HandleDeleteObject); - m_console.Commands.AddCommand("Objects", false, "delete object uuid", - "delete object uuid ", - "Delete a scene object by uuid", HandleDeleteObject); + m_console.Commands.AddCommand( + "Objects", false, "delete object uuid", + "delete object uuid ", + "Delete a scene object by uuid", HandleDeleteObject); - m_console.Commands.AddCommand("Objects", false, "delete object name", - "delete object name ", - "Delete a scene object by name", HandleDeleteObject); + m_console.Commands.AddCommand( + "Objects", false, "delete object name", + "delete object name [--regex] ", + "Delete a scene object by name.\nIf --regex is specified then the name is treatead as a regular expression", + HandleDeleteObject); - m_console.Commands.AddCommand("Objects", false, "delete object outside", - "delete object outside", - "Delete all scene objects outside region boundaries", HandleDeleteObject); + m_console.Commands.AddCommand( + "Objects", false, "delete object outside", + "delete object outside", + "Delete all scene objects outside region boundaries", HandleDeleteObject); m_console.Commands.AddCommand( "Objects", @@ -109,8 +117,9 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands "Objects", false, "show object name", - "show object name ", - "Show details of scene objects with the given name", HandleShowObjectByName); + "show object name [--regex] ", + "Show details of scene objects with the given name.\nIf --regex is specified then the name is treatead as a regular expression", + HandleShowObjectByName); m_console.Commands.AddCommand( "Objects", @@ -123,8 +132,9 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands "Objects", false, "show part name", - "show part name ", - "Show details of scene object parts with the given name", HandleShowPartByName); + "show part name [--regex] ", + "Show details of scene object parts with the given name.\nIf --regex is specified then the name is treatead as a regular expression", + HandleShowPartByName); } public void RemoveRegion(Scene scene) @@ -169,22 +179,38 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands m_console.OutputFormat(sb.ToString()); } - private void HandleShowObjectByName(string module, string[] cmd) + private void HandleShowObjectByName(string module, string[] cmdparams) { if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) return; - if (cmd.Length < 4) + bool useRegex = false; + OptionSet options = new OptionSet().Add("regex", v=> useRegex = v != null ); + + List mainParams = options.Parse(cmdparams); + + if (mainParams.Count < 4) { - m_console.OutputFormat("Usage: show object name "); + m_console.OutputFormat("Usage: show object name [--regex] "); return; } - string name = cmd[3]; + string name = mainParams[3]; List sceneObjects = new List(); + Action searchAction; + + if (useRegex) + { + Regex nameRegex = new Regex(name); + searchAction = so => { if (nameRegex.IsMatch(so.Name)) { sceneObjects.Add(so); }}; + } + else + { + searchAction = so => { if (so.Name == name) { sceneObjects.Add(so); }}; + } - m_scene.ForEachSOG(so => { if (so.Name == name) { sceneObjects.Add(so); }}); + m_scene.ForEachSOG(searchAction); if (sceneObjects.Count == 0) { @@ -235,22 +261,39 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands m_console.OutputFormat(sb.ToString()); } - private void HandleShowPartByName(string module, string[] cmd) + private void HandleShowPartByName(string module, string[] cmdparams) { if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) return; - if (cmd.Length < 4) + bool useRegex = false; + OptionSet options = new OptionSet().Add("regex", v=> useRegex = v != null ); + + List mainParams = options.Parse(cmdparams); + + if (mainParams.Count < 4) { - m_console.OutputFormat("Usage: show part name "); + m_console.OutputFormat("Usage: show part name [--regex] "); return; } - string name = cmd[3]; + string name = mainParams[3]; List parts = new List(); - m_scene.ForEachSOG(so => so.ForEachPart(sop => { if (sop.Name == name) { parts.Add(sop); } })); + Action searchAction; + + if (useRegex) + { + Regex nameRegex = new Regex(name); + searchAction = so => so.ForEachPart(sop => { if (nameRegex.IsMatch(sop.Name)) { parts.Add(sop); } }); + } + else + { + searchAction = so => so.ForEachPart(sop => { if (sop.Name == name) { parts.Add(sop); } }); + } + + m_scene.ForEachSOG(searchAction); if (parts.Count == 0) { @@ -312,105 +355,169 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands o = cmd[3]; } - List deletes = new List(); - + List deletes = null; UUID match; + bool requireConfirmation = true; switch (mode) { - case "owner": - if (!UUID.TryParse(o, out match)) - return; - - m_scene.ForEachSOG(delegate (SceneObjectGroup g) - { - if (g.OwnerID == match && !g.IsAttachment) - deletes.Add(g); - }); + case "owner": + if (!UUID.TryParse(o, out match)) + return; -// if (deletes.Count == 0) -// m_console.OutputFormat("No objects were found with owner {0}", match); + deletes = new List(); - break; + m_scene.ForEachSOG(delegate (SceneObjectGroup g) + { + if (g.OwnerID == match && !g.IsAttachment) + deletes.Add(g); + }); + + // if (deletes.Count == 0) + // m_console.OutputFormat("No objects were found with owner {0}", match); + + break; + + case "creator": + if (!UUID.TryParse(o, out match)) + return; - case "creator": - if (!UUID.TryParse(o, out match)) - return; + deletes = new List(); - m_scene.ForEachSOG(delegate (SceneObjectGroup g) - { - if (g.RootPart.CreatorID == match && !g.IsAttachment) - deletes.Add(g); - }); + m_scene.ForEachSOG(delegate (SceneObjectGroup g) + { + if (g.RootPart.CreatorID == match && !g.IsAttachment) + deletes.Add(g); + }); + + // if (deletes.Count == 0) + // m_console.OutputFormat("No objects were found with creator {0}", match); + + break; + + case "uuid": + if (!UUID.TryParse(o, out match)) + return; -// if (deletes.Count == 0) -// m_console.OutputFormat("No objects were found with creator {0}", match); + requireConfirmation = false; + deletes = new List(); + + m_scene.ForEachSOG(delegate (SceneObjectGroup g) + { + if (g.UUID == match && !g.IsAttachment) + deletes.Add(g); + }); + + // if (deletes.Count == 0) + // m_console.OutputFormat("No objects were found with uuid {0}", match); + + break; + + case "name": + deletes = GetDeleteCandidatesByName(module, cmd); + break; + + case "outside": + deletes = new List(); - break; + m_scene.ForEachSOG(delegate (SceneObjectGroup g) + { + SceneObjectPart rootPart = g.RootPart; + bool delete = false; + + if (rootPart.GroupPosition.Z < 0.0 || rootPart.GroupPosition.Z > 10000.0) + { + delete = true; + } + else + { + ILandObject parcel + = m_scene.LandChannel.GetLandObject(rootPart.GroupPosition.X, rootPart.GroupPosition.Y); + + if (parcel == null || parcel.LandData.Name == "NO LAND") + delete = true; + } + + if (delete && !g.IsAttachment && !deletes.Contains(g)) + deletes.Add(g); + }); + + if (deletes.Count == 0) + m_console.OutputFormat("No objects were found outside region bounds"); + + break; - case "uuid": - if (!UUID.TryParse(o, out match)) + default: + m_console.OutputFormat("Unrecognized mode {0}", mode); return; + } - m_scene.ForEachSOG(delegate (SceneObjectGroup g) - { - if (g.UUID == match && !g.IsAttachment) - deletes.Add(g); - }); - -// if (deletes.Count == 0) -// m_console.OutputFormat("No objects were found with uuid {0}", match); - - break; + if (deletes == null || deletes.Count <= 0) + return; - case "name": - m_scene.ForEachSOG(delegate (SceneObjectGroup g) + if (requireConfirmation) + { + string response = MainConsole.Instance.CmdPrompt( + string.Format( + "Are you sure that you want to delete {0} objects from {1}", + deletes.Count, m_scene.RegionInfo.RegionName), + "n"); + + if (response.ToLower() != "y") { - if (g.RootPart.Name == o && !g.IsAttachment) - deletes.Add(g); - }); - -// if (deletes.Count == 0) -// m_console.OutputFormat("No objects were found with name {0}", o); + MainConsole.Instance.OutputFormat( + "Aborting delete of {0} objects from {1}", deletes.Count, m_scene.RegionInfo.RegionName); - break; + return; + } + } - case "outside": - m_scene.ForEachSOG(delegate (SceneObjectGroup g) - { - SceneObjectPart rootPart = g.RootPart; - bool delete = false; + m_console.OutputFormat("Deleting {0} objects in {1}", deletes.Count, m_scene.RegionInfo.RegionName); - if (rootPart.GroupPosition.Z < 0.0 || rootPart.GroupPosition.Z > 10000.0) - { - delete = true; - } - else - { - ILandObject parcel - = m_scene.LandChannel.GetLandObject(rootPart.GroupPosition.X, rootPart.GroupPosition.Y); + foreach (SceneObjectGroup g in deletes) + { + m_console.OutputFormat("Deleting object {0} {1}", g.UUID, g.Name); + m_scene.DeleteSceneObject(g, false); + } + } - if (parcel == null || parcel.LandData.Name == "NO LAND") - delete = true; - } + private List GetDeleteCandidatesByName(string module, string[] cmdparams) + { + if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) + return null; - if (delete && !g.IsAttachment && !deletes.Contains(g)) - deletes.Add(g); - }); + bool useRegex = false; + OptionSet options = new OptionSet().Add("regex", v=> useRegex = v != null ); -// if (deletes.Count == 0) -// m_console.OutputFormat("No objects were found outside region bounds"); + List mainParams = options.Parse(cmdparams); - break; + if (mainParams.Count < 4) + { + m_console.OutputFormat("Usage: delete object name [--regex] "); + return null; } - m_console.OutputFormat("Deleting {0} objects in {1}", deletes.Count, m_scene.RegionInfo.RegionName); + string name = mainParams[3]; - foreach (SceneObjectGroup g in deletes) + List sceneObjects = new List(); + Action searchAction; + + if (useRegex) { - m_console.OutputFormat("Deleting object {0} {1}", g.UUID, g.Name); - m_scene.DeleteSceneObject(g, false); + Regex nameRegex = new Regex(name); + searchAction = so => { if (nameRegex.IsMatch(so.Name)) { sceneObjects.Add(so); }}; + } + else + { + searchAction = so => { if (so.Name == name) { sceneObjects.Add(so); }}; } + + m_scene.ForEachSOG(searchAction); + + if (sceneObjects.Count == 0) + m_console.OutputFormat("No objects with name {0} found in {1}", name, m_scene.RegionInfo.RegionName); + + return sceneObjects; } } } \ No newline at end of file -- cgit v1.1 From 1b5ce8c10e492308eeb44c82fee0c65cec855327 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 15 May 2012 23:43:59 +0100 Subject: Fix issue where loading OARs could sometimes result in link numbers being reordered. This was because the parts in scene objects were sometimes not serialized in link order. This is perfectly fine since the parts still have the right link numbers, but an extra fix to adjust for this had not been done in the SerialiserModule methods that OAR loading used. Add regression test for same. Addresses http://opensimulator.org/mantis/view.php?id=5948, http://opensimulator.org/mantis/view.php?id=5749 --- .../World/Archiver/ArchiveReadRequest.cs | 4 +- .../World/Archiver/Tests/ArchiverTests.cs | 53 ++++++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region/CoreModules') diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs index bf0ff75..11eca12 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs @@ -41,6 +41,7 @@ using OpenSim.Framework.Serialization.External; using OpenSim.Region.CoreModules.World.Terrain; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.Framework.Scenes.Serialization; using OpenSim.Services.Interfaces; namespace OpenSim.Region.CoreModules.World.Archiver @@ -266,7 +267,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver } */ - SceneObjectGroup sceneObject = serialiser.DeserializeGroupFromXml2(serialisedSceneObject); + SceneObjectGroup sceneObject = SceneObjectSerializer.FromXml2Format(serialisedSceneObject); +// SceneObjectGroup sceneObject = serialiser.DeserializeGroupFromXml2(serialisedSceneObject); bool isTelehub = (sceneObject.UUID == oldTelehubUUID); diff --git a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs index 394ca27..5deaf52 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs @@ -292,6 +292,59 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests } /// + /// Test loading an OpenSim Region Archive where the scene object parts are not ordered by link number (e.g. + /// 2 can come after 3). + /// + [Test] + public void TestLoadOarUnorderedParts() + { + TestHelpers.InMethod(); + + UUID ownerId = TestHelpers.ParseTail(0xaaaa); + + MemoryStream archiveWriteStream = new MemoryStream(); + TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream); + + tar.WriteFile( + ArchiveConstants.CONTROL_FILE_PATH, + new ArchiveWriteRequestPreparation(null, (Stream)null, Guid.Empty).CreateControlFile(new Dictionary())); + + SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, ownerId, "obj1-", 0x11); + SceneObjectPart sop2 + = SceneHelpers.CreateSceneObjectPart("obj1-Part2", TestHelpers.ParseTail(0x12), ownerId); + SceneObjectPart sop3 + = SceneHelpers.CreateSceneObjectPart("obj1-Part3", TestHelpers.ParseTail(0x13), ownerId); + + // Add the parts so they will be written out in reverse order to the oar + sog1.AddPart(sop3); + sop3.LinkNum = 3; + sog1.AddPart(sop2); + sop2.LinkNum = 2; + + tar.WriteFile( + ArchiveConstants.CreateOarObjectPath(sog1.Name, sog1.UUID, sog1.AbsolutePosition), + SceneObjectSerializer.ToXml2Format(sog1)); + + tar.Close(); + + MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray()); + + lock (this) + { + m_scene.EventManager.OnOarFileLoaded += LoadCompleted; + m_archiverModule.DearchiveRegion(archiveReadStream); + } + + Assert.That(m_lastErrorMessage, Is.Null); + + SceneObjectPart part2 = m_scene.GetSceneObjectPart("obj1-Part2"); + Assert.That(part2.LinkNum, Is.EqualTo(2)); + + SceneObjectPart part3 = m_scene.GetSceneObjectPart("obj1-Part3"); + Assert.That(part3.LinkNum, Is.EqualTo(3)); + } + + /// /// Test loading an OpenSim Region Archive. /// [Test] -- cgit v1.1 From 23ae24b4061f7c1e1bc1c0d5428374ccf4e25891 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 16 May 2012 00:10:42 +0100 Subject: Route OAR SOG loading through the common SceneObjectSerializer.FromXml2Format() rather than the functionally identical but buggy Xml2ToSOG(). Remove buggy Xml2ToSOG(). --- OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'OpenSim/Region/CoreModules') diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs index 11eca12..2b61800 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs @@ -267,8 +267,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver } */ - SceneObjectGroup sceneObject = SceneObjectSerializer.FromXml2Format(serialisedSceneObject); -// SceneObjectGroup sceneObject = serialiser.DeserializeGroupFromXml2(serialisedSceneObject); + SceneObjectGroup sceneObject = serialiser.DeserializeGroupFromXml2(serialisedSceneObject); bool isTelehub = (sceneObject.UUID == oldTelehubUUID); -- cgit v1.1