From 289c21099cf3ce0a2e3392436541b67d0961d8e8 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 24 Aug 2010 16:50:31 +0100 Subject: [PATCH 01/10] Add automated test at the opensim 'api' level to check that a given item goes to the correct directory Also removes some mono compiler warnings --- OpenSim/Data/Tests/EstateTests.cs | 6 - OpenSim/Data/Tests/InventoryTests.cs | 4 - OpenSim/Data/Tests/RegionTests.cs | 4 - .../LocalInventoryServiceConnector.cs | 17 ++- .../RemoteXInventoryServiceConnector.cs | 7 ++ .../Framework/Scenes/Scene.Inventory.cs | 2 +- .../Scenes/Tests/TaskInventoryTests.cs | 104 ++++++++++++++++++ .../InventoryService/InventoryService.cs | 9 +- .../Tests/Common/Mock/MockInventoryService.cs | 12 +- .../Common/Mock/TestInventoryDataPlugin.cs | 31 +++++- .../Tests/Common/Setup/SceneSetupHelpers.cs | 6 + 11 files changed, 170 insertions(+), 32 deletions(-) create mode 100644 OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs diff --git a/OpenSim/Data/Tests/EstateTests.cs b/OpenSim/Data/Tests/EstateTests.cs index d6eed3dadd..fbf8ba658e 100644 --- a/OpenSim/Data/Tests/EstateTests.cs +++ b/OpenSim/Data/Tests/EstateTests.cs @@ -37,11 +37,6 @@ using log4net; using System.Reflection; using System.Data.Common; -#if !NUNIT25 -using NUnit.Framework.SyntaxHelpers; -#endif - - // DBMS-specific: using MySql.Data.MySqlClient; using OpenSim.Data.MySQL; @@ -52,7 +47,6 @@ using OpenSim.Data.MSSQL; using Mono.Data.Sqlite; using OpenSim.Data.SQLite; - namespace OpenSim.Data.Tests { diff --git a/OpenSim/Data/Tests/InventoryTests.cs b/OpenSim/Data/Tests/InventoryTests.cs index c22e26c3c9..3205bfa7f3 100644 --- a/OpenSim/Data/Tests/InventoryTests.cs +++ b/OpenSim/Data/Tests/InventoryTests.cs @@ -37,10 +37,6 @@ using log4net; using System.Reflection; using System.Data.Common; -#if !NUNIT25 -using NUnit.Framework.SyntaxHelpers; -#endif - // DBMS-specific: using MySql.Data.MySqlClient; using OpenSim.Data.MySQL; diff --git a/OpenSim/Data/Tests/RegionTests.cs b/OpenSim/Data/Tests/RegionTests.cs index 3cd9e0be1e..29bf5a3418 100644 --- a/OpenSim/Data/Tests/RegionTests.cs +++ b/OpenSim/Data/Tests/RegionTests.cs @@ -40,10 +40,6 @@ using log4net; using System.Reflection; using System.Data.Common; -#if !NUNIT25 -using NUnit.Framework.SyntaxHelpers; -#endif - // DBMS-specific: using MySql.Data.MySqlClient; using OpenSim.Data.MySQL; diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs index 350ad66457..915b59ec29 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs @@ -218,24 +218,35 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory public bool AddItem(InventoryItemBase item) { - m_log.DebugFormat( - "[LOCAL INVENTORY SERVICES CONNECTOR]: Adding inventory item {0} to user {1} folder {2}", - item.Name, item.Owner, item.Folder); +// m_log.DebugFormat( +// "[LOCAL INVENTORY SERVICES CONNECTOR]: Adding inventory item {0} to user {1} folder {2}", +// item.Name, item.Owner, item.Folder); if (UUID.Zero == item.Folder) { InventoryFolderBase f = m_InventoryService.GetFolderForType(item.Owner, (AssetType)item.AssetType); if (f != null) { +// m_log.DebugFormat( +// "[LOCAL INVENTORY SERVICES CONNECTOR]: Found folder {0} type {1} for item {2}", +// f.Name, (AssetType)f.Type, item.Name); + item.Folder = f.ID; } else { f = m_InventoryService.GetRootFolder(item.Owner); if (f != null) + { item.Folder = f.ID; + } else + { +// m_log.WarnFormat( +// "[LOCAL INVENTORY SERVICES CONNECTOR]: Could not find root folder for {0} when trying to add item {1} with no parent folder specified", +// item.Owner, item.Name); return false; + } } } diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs index 7ac3bb9f4e..4211fa9b07 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs @@ -240,9 +240,16 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory { f = m_RemoteConnector.GetRootFolder(item.Owner); if (f != null) + { item.Folder = f.ID; + } else + { + m_log.WarnFormat( + "[LOCAL INVENTORY SERVICES CONNECTOR]: Could not find root folder for {0} when trying to add item {1} with no parent folder specified", + item.Owner, item.Name); return false; + } } } diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 241e100d00..fa9653f7af 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -106,7 +106,7 @@ namespace OpenSim.Region.Framework.Scenes else { m_log.WarnFormat( - "[AGENT INVENTORY]: Agent {1} could not add item {2} {3}", + "[AGENT INVENTORY]: Agent {0} could not add item {1} {2}", AgentID, item.Name, item.ID); return; diff --git a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs new file mode 100644 index 0000000000..f848e80816 --- /dev/null +++ b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs @@ -0,0 +1,104 @@ +/* + * 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.Collections.Generic; +using System.Reflection; +using System.Text; +using System.Threading; +using System.Timers; +using Timer=System.Timers.Timer; +using Nini.Config; +using NUnit.Framework; +using NUnit.Framework.SyntaxHelpers; +using OpenMetaverse; +using OpenMetaverse.Assets; +using OpenSim.Framework; +using OpenSim.Framework.Communications; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.CoreModules.Avatar.Inventory.Archiver; +using OpenSim.Region.CoreModules.World.Serialiser; +using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; +using OpenSim.Tests.Common; +using OpenSim.Tests.Common.Mock; +using OpenSim.Tests.Common.Setup; + +namespace OpenSim.Region.Framework.Tests +{ + [TestFixture] + public class TaskInventoryTests + { + /// + /// Test MoveTaskInventoryItem where the item has no parent folder assigned. + /// + /// This should place it in the most suitable user folder. + [Test] + public void TestMoveTaskInventoryItemNoParent() + { + TestHelper.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + Scene scene = SceneSetupHelpers.SetupScene("inventory"); + + // Create user + string userFirstName = "Jock"; + string userLastName = "Stirrup"; + string userPassword = "troll"; + UUID userId = UUID.Parse("00000000-0000-0000-0000-000000000020"); + UserProfileTestUtils.CreateUserWithInventory(scene, userFirstName, userLastName, userId, userPassword); + + // Create scene object + string part1Name = "part1"; + UUID part1Id = UUID.Parse("10000000-0000-0000-0000-000000000000"); + SceneObjectPart part1 + = new SceneObjectPart(userId, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero) + { Name = part1Name, UUID = part1Id }; + SceneObjectGroup so = new SceneObjectGroup(part1); + + // Create scene object inventory item + AssetNotecard nc = new AssetNotecard("Hello World!"); + UUID ncAssetUuid = new UUID("00000000-0000-0000-1000-000000000000"); + UUID ncItemUuid = new UUID("00000000-0000-0000-1100-000000000000"); + AssetBase ncAsset + = AssetHelpers.CreateAsset(ncAssetUuid, AssetType.Notecard, nc.AssetData, UUID.Zero); + scene.AssetService.Store(ncAsset); + TaskInventoryItem ncItem + = new TaskInventoryItem + { Name = "ncItem", AssetID = ncAssetUuid, ItemID = ncItemUuid, + Type = (int)AssetType.Notecard, InvType = (int)InventoryType.Notecard }; + part1.Inventory.AddInventoryItem(ncItem, true); + + // Perform test + scene.MoveTaskInventoryItem(userId, UUID.Zero, part1, ncItemUuid); + + InventoryItemBase ncUserItem + = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, userId, "Notecards/ncItem"); + Assert.That(ncUserItem, Is.Not.Null, "Notecards/ncItem was not found"); + } + } +} \ No newline at end of file diff --git a/OpenSim/Services/InventoryService/InventoryService.cs b/OpenSim/Services/InventoryService/InventoryService.cs index fbcd6634e7..86bca79d6b 100644 --- a/OpenSim/Services/InventoryService/InventoryService.cs +++ b/OpenSim/Services/InventoryService/InventoryService.cs @@ -268,15 +268,22 @@ namespace OpenSim.Services.InventoryService public InventoryFolderBase GetFolderForType(UUID userID, AssetType type) { +// m_log.DebugFormat("[INVENTORY SERVICE]: Looking for folder type {0} for user {1}", type, userID); + InventoryFolderBase root = m_Database.getUserRootFolder(userID); if (root != null) { List folders = RequestSubFolders(root.ID); foreach (InventoryFolderBase folder in folders) - { + { if (folder.Type == (short)type) + { +// m_log.DebugFormat( +// "[INVENTORY SERVICE]: Found folder {0} type {1}", folder.Name, (AssetType)folder.Type); + return folder; + } } } diff --git a/OpenSim/Tests/Common/Mock/MockInventoryService.cs b/OpenSim/Tests/Common/Mock/MockInventoryService.cs index 1ea4bc1059..4ac1078795 100644 --- a/OpenSim/Tests/Common/Mock/MockInventoryService.cs +++ b/OpenSim/Tests/Common/Mock/MockInventoryService.cs @@ -37,13 +37,9 @@ namespace OpenSim.Tests.Common.Mock { public class MockInventoryService : IInventoryService { - public MockInventoryService() - { - } + public MockInventoryService() {} - public MockInventoryService(IConfigSource config) - { - } + public MockInventoryService(IConfigSource config) {} /// /// @@ -140,7 +136,7 @@ namespace OpenSim.Tests.Common.Mock public bool AddItem(InventoryItemBase item) { - return false; + return true; } public bool UpdateItem(InventoryItemBase item) @@ -187,4 +183,4 @@ namespace OpenSim.Tests.Common.Mock return 1; } } -} +} \ No newline at end of file diff --git a/OpenSim/Tests/Common/Mock/TestInventoryDataPlugin.cs b/OpenSim/Tests/Common/Mock/TestInventoryDataPlugin.cs index 7c4f689502..ed0b1a6a9a 100644 --- a/OpenSim/Tests/Common/Mock/TestInventoryDataPlugin.cs +++ b/OpenSim/Tests/Common/Mock/TestInventoryDataPlugin.cs @@ -42,7 +42,7 @@ namespace OpenSim.Tests.Common.Mock /// public class TestInventoryDataPlugin : IInventoryDataPlugin { -// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); /// /// Inventory folders @@ -84,14 +84,19 @@ namespace OpenSim.Tests.Common.Mock public List getInventoryInFolder(UUID folderID) { -// m_log.DebugFormat("[MOCK INV DB]: Getting items in folder {0}", folderID); + InventoryFolderBase folder = m_folders[folderID]; + + m_log.DebugFormat("[MOCK INV DB]: Getting items in folder {0} {1}", folder.Name, folder.ID); List items = new List(); foreach (InventoryItemBase item in m_items.Values) { if (item.Folder == folderID) + { + m_log.DebugFormat("[MOCK INV DB]: getInventoryInFolder() adding item {0}", item.Name); items.Add(item); + } } return items; @@ -101,7 +106,7 @@ namespace OpenSim.Tests.Common.Mock public InventoryFolderBase getUserRootFolder(UUID user) { -// m_log.DebugFormat("[MOCK INV DB]: Looking for root folder for {0}", user); + m_log.DebugFormat("[MOCK INV DB]: Looking for root folder for {0}", user); InventoryFolderBase folder = null; m_rootFolders.TryGetValue(user, out folder); @@ -111,12 +116,22 @@ namespace OpenSim.Tests.Common.Mock public List getInventoryFolders(UUID parentID) { + InventoryFolderBase parentFolder = m_folders[parentID]; + + m_log.DebugFormat("[MOCK INV DB]: Getting folders in folder {0} {1}", parentFolder.Name, parentFolder.ID); + List folders = new List(); foreach (InventoryFolderBase folder in m_folders.Values) { if (folder.ParentID == parentID) + { + m_log.DebugFormat( + "[MOCK INV DB]: Found folder {0} {1} in {2} {3}", + folder.Name, folder.ID, parentFolder.Name, parentFolder.ID); + folders.Add(folder); + } } return folders; @@ -137,6 +152,10 @@ namespace OpenSim.Tests.Common.Mock public void addInventoryFolder(InventoryFolderBase folder) { + m_log.DebugFormat( + "[MOCK INV DB]: Adding inventory folder {0} {1} type {2}", + folder.Name, folder.ID, (AssetType)folder.Type); + m_folders[folder.ID] = folder; if (folder.ParentID == UUID.Zero) @@ -166,8 +185,10 @@ namespace OpenSim.Tests.Common.Mock public void addInventoryItem(InventoryItemBase item) { -// m_log.DebugFormat( -// "[MOCK INV DB]: Adding inventory item {0} {1} in {2}", item.Name, item.ID, item.Folder); + InventoryFolderBase folder = m_folders[item.Folder]; + + m_log.DebugFormat( + "[MOCK INV DB]: Adding inventory item {0} {1} in {2} {3}", item.Name, item.ID, folder.Name, folder.ID); m_items[item.ID] = item; } diff --git a/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs b/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs index eaa0d33b4b..d9ded2d0c4 100644 --- a/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs +++ b/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs @@ -285,10 +285,16 @@ namespace OpenSim.Tests.Common.Setup config.AddConfig("Modules"); config.AddConfig("InventoryService"); config.Configs["Modules"].Set("InventoryServices", "LocalInventoryServicesConnector"); + if (real) + { config.Configs["InventoryService"].Set("LocalServiceModule", "OpenSim.Services.InventoryService.dll:InventoryService"); + } else + { config.Configs["InventoryService"].Set("LocalServiceModule", "OpenSim.Tests.Common.dll:MockInventoryService"); + } + config.Configs["InventoryService"].Set("StorageProvider", "OpenSim.Tests.Common.dll"); inventoryService.Initialise(config); inventoryService.AddRegion(testScene); From 35f719ae2f9e58cfd46a6c0082238c500a3454f3 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 24 Aug 2010 17:04:54 +0100 Subject: [PATCH 02/10] refactor TestMoveTaskInventoryItemNoParent() --- .../Scenes/Tests/TaskInventoryTests.cs | 75 +++++++++++-------- 1 file changed, 44 insertions(+), 31 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs index f848e80816..ed2f324fb9 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs @@ -44,6 +44,7 @@ using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.CoreModules.Avatar.Inventory.Archiver; using OpenSim.Region.CoreModules.World.Serialiser; using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; +using OpenSim.Services.Interfaces; using OpenSim.Tests.Common; using OpenSim.Tests.Common.Mock; using OpenSim.Tests.Common.Setup; @@ -53,6 +54,42 @@ namespace OpenSim.Region.Framework.Tests [TestFixture] public class TaskInventoryTests { + protected UserAccount CreateUser(Scene scene) + { + string userFirstName = "Jock"; + string userLastName = "Stirrup"; + string userPassword = "troll"; + UUID userId = UUID.Parse("00000000-0000-0000-0000-000000000020"); + return UserProfileTestUtils.CreateUserWithInventory(scene, userFirstName, userLastName, userId, userPassword); + } + + protected SceneObjectGroup CreateSO1(Scene scene, UUID ownerId) + { + string part1Name = "part1"; + UUID part1Id = UUID.Parse("10000000-0000-0000-0000-000000000000"); + SceneObjectPart part1 + = new SceneObjectPart(ownerId, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero) + { Name = part1Name, UUID = part1Id }; + return new SceneObjectGroup(part1); + } + + protected TaskInventoryItem CreateSOItem1(Scene scene, SceneObjectPart part) + { + AssetNotecard nc = new AssetNotecard("Hello World!"); + UUID ncAssetUuid = new UUID("00000000-0000-0000-1000-000000000000"); + UUID ncItemUuid = new UUID("00000000-0000-0000-1100-000000000000"); + AssetBase ncAsset + = AssetHelpers.CreateAsset(ncAssetUuid, AssetType.Notecard, nc.AssetData, UUID.Zero); + scene.AssetService.Store(ncAsset); + TaskInventoryItem ncItem + = new TaskInventoryItem + { Name = "ncItem", AssetID = ncAssetUuid, ItemID = ncItemUuid, + Type = (int)AssetType.Notecard, InvType = (int)InventoryType.Notecard }; + part.Inventory.AddInventoryItem(ncItem, true); + + return ncItem; + } + /// /// Test MoveTaskInventoryItem where the item has no parent folder assigned. /// @@ -64,40 +101,16 @@ namespace OpenSim.Region.Framework.Tests // log4net.Config.XmlConfigurator.Configure(); Scene scene = SceneSetupHelpers.SetupScene("inventory"); - - // Create user - string userFirstName = "Jock"; - string userLastName = "Stirrup"; - string userPassword = "troll"; - UUID userId = UUID.Parse("00000000-0000-0000-0000-000000000020"); - UserProfileTestUtils.CreateUserWithInventory(scene, userFirstName, userLastName, userId, userPassword); - - // Create scene object - string part1Name = "part1"; - UUID part1Id = UUID.Parse("10000000-0000-0000-0000-000000000000"); - SceneObjectPart part1 - = new SceneObjectPart(userId, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero) - { Name = part1Name, UUID = part1Id }; - SceneObjectGroup so = new SceneObjectGroup(part1); - - // Create scene object inventory item - AssetNotecard nc = new AssetNotecard("Hello World!"); - UUID ncAssetUuid = new UUID("00000000-0000-0000-1000-000000000000"); - UUID ncItemUuid = new UUID("00000000-0000-0000-1100-000000000000"); - AssetBase ncAsset - = AssetHelpers.CreateAsset(ncAssetUuid, AssetType.Notecard, nc.AssetData, UUID.Zero); - scene.AssetService.Store(ncAsset); - TaskInventoryItem ncItem - = new TaskInventoryItem - { Name = "ncItem", AssetID = ncAssetUuid, ItemID = ncItemUuid, - Type = (int)AssetType.Notecard, InvType = (int)InventoryType.Notecard }; - part1.Inventory.AddInventoryItem(ncItem, true); + UserAccount user1 = CreateUser(scene); + SceneObjectGroup sog1 = CreateSO1(scene, user1.PrincipalID); + SceneObjectPart sop1 = sog1.RootPart; + TaskInventoryItem sopItem1 = CreateSOItem1(scene, sop1); // Perform test - scene.MoveTaskInventoryItem(userId, UUID.Zero, part1, ncItemUuid); - + scene.MoveTaskInventoryItem(user1.PrincipalID, UUID.Zero, sop1, sopItem1.ItemID); + InventoryItemBase ncUserItem - = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, userId, "Notecards/ncItem"); + = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, user1.PrincipalID, "Notecards/ncItem"); Assert.That(ncUserItem, Is.Not.Null, "Notecards/ncItem was not found"); } } From 8bb073d99af8aa5873b4adb6e0e985e98d804c62 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 24 Aug 2010 17:06:04 +0100 Subject: [PATCH 03/10] minor: stop test using obsolete property --- OpenSim/Region/Framework/Scenes/Tests/EntityManagerTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/Tests/EntityManagerTests.cs b/OpenSim/Region/Framework/Scenes/Tests/EntityManagerTests.cs index fc66c85b84..3e2a2af94b 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/EntityManagerTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/EntityManagerTests.cs @@ -134,7 +134,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests sop.Text = RandomName(); sop.SitName = RandomName(); sop.TouchName = RandomName(); - sop.ObjectFlags |= (uint)PrimFlags.Phantom; + sop.Flags |= PrimFlags.Phantom; SceneObjectGroup sog = new SceneObjectGroup(sop); scene.AddNewSceneObject(sog, false); From 46d06b6c4c858779472220db88dc64bae4489c38 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 24 Aug 2010 17:10:52 +0100 Subject: [PATCH 04/10] add test to check move of task item to user inventory when a target folder is explicitly given --- .../Scenes/Tests/TaskInventoryTests.cs | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs index ed2f324fb9..da8199ddf4 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs @@ -90,6 +90,32 @@ namespace OpenSim.Region.Framework.Tests return ncItem; } + /// + /// Test MoveTaskInventoryItem where the item has no parent folder assigned. + /// + /// This should place it in the most suitable user folder. + [Test] + public void TestMoveTaskInventoryItem() + { + TestHelper.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + Scene scene = SceneSetupHelpers.SetupScene("inventory"); + UserAccount user1 = CreateUser(scene); + SceneObjectGroup sog1 = CreateSO1(scene, user1.PrincipalID); + SceneObjectPart sop1 = sog1.RootPart; + TaskInventoryItem sopItem1 = CreateSOItem1(scene, sop1); + InventoryFolderBase folder + = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, user1.PrincipalID, "Objects")[0]; + + // Perform test + scene.MoveTaskInventoryItem(user1.PrincipalID, folder.ID, sop1, sopItem1.ItemID); + + InventoryItemBase ncUserItem + = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, user1.PrincipalID, "Objects/ncItem"); + Assert.That(ncUserItem, Is.Not.Null, "Objects/ncItem was not found"); + } + /// /// Test MoveTaskInventoryItem where the item has no parent folder assigned. /// From 07d5a0779a8330a56fd6ca6d30918de7c8161f98 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 24 Aug 2010 20:53:25 +0100 Subject: [PATCH 05/10] refactor: make RezObject() more readable --- .../Framework/Scenes/Scene.Inventory.cs | 157 +++++++++--------- 1 file changed, 78 insertions(+), 79 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index fa9653f7af..9c62ad392b 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1951,7 +1951,7 @@ namespace OpenSim.Region.Framework.Scenes remoteClient, itemID, RayEnd, RayStart, RayTargetID, BypassRayCast, RayEndIsIntersection, RezSelected, RemoveItem, fromTaskID, false); } - + /// /// Rez an object into the scene from a prim's inventory. /// @@ -1966,95 +1966,94 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectPart sourcePart, TaskInventoryItem item, Vector3 pos, Quaternion rot, Vector3 vel, int param) { - // Rez object - if (item != null) + if (null == item) + return null; + + UUID ownerID = item.OwnerID; + AssetBase rezAsset = AssetService.Get(item.AssetID.ToString()); + + if (null == rezAsset) + return null; + + string xmlData = Utils.BytesToString(rezAsset.Data); + SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); + + if (!Permissions.CanRezObject(group.Children.Count, ownerID, pos)) + return null; + + group.ResetIDs(); + + AddNewSceneObject(group, true); + + // we set it's position in world. + group.AbsolutePosition = pos; + + SceneObjectPart rootPart = group.GetChildPart(group.UUID); + + // Since renaming the item in the inventory does not affect the name stored + // in the serialization, transfer the correct name from the inventory to the + // object itself before we rez. + rootPart.Name = item.Name; + rootPart.Description = item.Description; + + List partList = new List(group.Children.Values); + + group.SetGroup(sourcePart.GroupID, null); + + if ((rootPart.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0) { - UUID ownerID = item.OwnerID; - - AssetBase rezAsset = AssetService.Get(item.AssetID.ToString()); - - if (rezAsset != null) + if (Permissions.PropagatePermissions()) { - string xmlData = Utils.BytesToString(rezAsset.Data); - SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); - - if (!Permissions.CanRezObject(group.Children.Count, ownerID, pos)) - { - return null; - } - group.ResetIDs(); - - AddNewSceneObject(group, true); - - // we set it's position in world. - group.AbsolutePosition = pos; - - SceneObjectPart rootPart = group.GetChildPart(group.UUID); - - // Since renaming the item in the inventory does not affect the name stored - // in the serialization, transfer the correct name from the inventory to the - // object itself before we rez. - rootPart.Name = item.Name; - rootPart.Description = item.Description; - - List partList = new List(group.Children.Values); - - group.SetGroup(sourcePart.GroupID, null); - - if ((rootPart.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0) - { - if (Permissions.PropagatePermissions()) - { - foreach (SceneObjectPart part in partList) - { - part.EveryoneMask = item.EveryonePermissions; - part.NextOwnerMask = item.NextPermissions; - } - group.ApplyNextOwnerPermissions(); - } - } - foreach (SceneObjectPart part in partList) { - if ((part.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0) - { - part.LastOwnerID = part.OwnerID; - part.OwnerID = item.OwnerID; - part.Inventory.ChangeInventoryOwner(item.OwnerID); - } part.EveryoneMask = item.EveryonePermissions; part.NextOwnerMask = item.NextPermissions; } - rootPart.TrimPermissions(); - - if (group.RootPart.Shape.PCode == (byte)PCode.Prim) - { - group.ClearPartAttachmentData(); - } - - group.UpdateGroupRotationR(rot); - - //group.ApplyPhysics(m_physicalPrim); - if (group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical && vel != Vector3.Zero) - { - group.RootPart.ApplyImpulse((vel * group.GetMass()), false); - group.Velocity = vel; - rootPart.ScheduleFullUpdate(); - } - group.CreateScriptInstances(param, true, DefaultScriptEngine, 2); - rootPart.ScheduleFullUpdate(); - - if (!Permissions.BypassPermissions()) - { - if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) - sourcePart.Inventory.RemoveInventoryItem(item.ItemID); - } - return rootPart.ParentGroup; + group.ApplyNextOwnerPermissions(); } } - return null; + foreach (SceneObjectPart part in partList) + { + if ((part.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0) + { + part.LastOwnerID = part.OwnerID; + part.OwnerID = item.OwnerID; + part.Inventory.ChangeInventoryOwner(item.OwnerID); + } + + part.EveryoneMask = item.EveryonePermissions; + part.NextOwnerMask = item.NextPermissions; + } + + rootPart.TrimPermissions(); + + if (group.RootPart.Shape.PCode == (byte)PCode.Prim) + { + group.ClearPartAttachmentData(); + } + + group.UpdateGroupRotationR(rot); + + //group.ApplyPhysics(m_physicalPrim); + if (group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical && vel != Vector3.Zero) + { + group.RootPart.ApplyImpulse((vel * group.GetMass()), false); + group.Velocity = vel; + rootPart.ScheduleFullUpdate(); + } + + group.CreateScriptInstances(param, true, DefaultScriptEngine, 2); + rootPart.ScheduleFullUpdate(); + + if (!Permissions.BypassPermissions()) + { + if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) + sourcePart.Inventory.RemoveInventoryItem(item.ItemID); + } + + return rootPart.ParentGroup; } public virtual bool returnObjects(SceneObjectGroup[] returnobjects, UUID AgentId) From d69e992665495b98fac4ae8c74266294e85804e6 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 24 Aug 2010 23:25:19 +0100 Subject: [PATCH 06/10] Split out actual scene object insertion code from Scene.Inventory.RezObject and move into SceneGraph.AddNewSceneObject() The new SceneGraph method is more consumable by region modules that want to extract objects from inventory and add them to the scene in separate stages. This change also reduces the number of redundant client updates scheduled when an object is rezzed directly by a script or region module This code does not touch direct rez by a user --- .../Framework/Scenes/Scene.Inventory.cs | 33 +++++------------ OpenSim/Region/Framework/Scenes/Scene.cs | 18 +++++++++- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 36 +++++++++++++++++++ 3 files changed, 62 insertions(+), 25 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 9c62ad392b..01be491573 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1983,11 +1983,6 @@ namespace OpenSim.Region.Framework.Scenes group.ResetIDs(); - AddNewSceneObject(group, true); - - // we set it's position in world. - group.AbsolutePosition = pos; - SceneObjectPart rootPart = group.GetChildPart(group.UUID); // Since renaming the item in the inventory does not affect the name stored @@ -2027,31 +2022,21 @@ namespace OpenSim.Region.Framework.Scenes part.NextOwnerMask = item.NextPermissions; } - rootPart.TrimPermissions(); - - if (group.RootPart.Shape.PCode == (byte)PCode.Prim) - { - group.ClearPartAttachmentData(); - } - - group.UpdateGroupRotationR(rot); - - //group.ApplyPhysics(m_physicalPrim); - if (group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical && vel != Vector3.Zero) - { - group.RootPart.ApplyImpulse((vel * group.GetMass()), false); - group.Velocity = vel; - rootPart.ScheduleFullUpdate(); - } - - group.CreateScriptInstances(param, true, DefaultScriptEngine, 2); - rootPart.ScheduleFullUpdate(); + rootPart.TrimPermissions(); if (!Permissions.BypassPermissions()) { if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) sourcePart.Inventory.RemoveInventoryItem(item.ItemID); } + + AddNewSceneObject(group, true, pos, rot, vel); + + // We can only call this after adding the scene object, since the scene object references the scene + // to find out if scripts should be activated at all. + group.CreateScriptInstances(param, true, DefaultScriptEngine, 2); + + group.ScheduleGroupForFullUpdate(); return rootPart.ParentGroup; } diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index a14762841d..b808c6d74c 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -42,7 +42,6 @@ using OpenMetaverse.Imaging; using OpenSim.Framework; using OpenSim.Services.Interfaces; using OpenSim.Framework.Communications; - using OpenSim.Framework.Console; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes.Scripting; @@ -2008,6 +2007,23 @@ namespace OpenSim.Region.Framework.Scenes { return m_sceneGraph.AddNewSceneObject(sceneObject, attachToBackup, sendClientUpdates); } + + /// + /// Add a newly created object to the scene. + /// + /// + /// This method does not send updates to the client - callers need to handle this themselves. + /// + /// + /// Position of the object + /// Rotation of the object + /// Velocity of the object. This parameter only has an effect if the object is physical + /// + public bool AddNewSceneObject( + SceneObjectGroup sceneObject, bool attachToBackup, Vector3 pos, Quaternion rot, Vector3 vel) + { + return m_sceneGraph.AddNewSceneObject(sceneObject, attachToBackup, pos, rot, vel); + } /// /// Delete every object from the scene. This does not include attachments worn by avatars. diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 9f38a999de..31faeec620 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -292,6 +292,42 @@ namespace OpenSim.Region.Framework.Scenes return AddSceneObject(sceneObject, attachToBackup, sendClientUpdates); } + + /// + /// Add a newly created object to the scene. + /// + /// + /// This method does not send updates to the client - callers need to handle this themselves. + /// + /// + /// Position of the object + /// Rotation of the object + /// Velocity of the object. This parameter only has an effect if the object is physical + /// + public bool AddNewSceneObject( + SceneObjectGroup sceneObject, bool attachToBackup, Vector3 pos, Quaternion rot, Vector3 vel) + { + AddNewSceneObject(sceneObject, true, false); + + // we set it's position in world. + sceneObject.AbsolutePosition = pos; + + if (sceneObject.RootPart.Shape.PCode == (byte)PCode.Prim) + { + sceneObject.ClearPartAttachmentData(); + } + + sceneObject.UpdateGroupRotationR(rot); + + //group.ApplyPhysics(m_physicalPrim); + if (sceneObject.RootPart.PhysActor != null && sceneObject.RootPart.PhysActor.IsPhysical && vel != Vector3.Zero) + { + sceneObject.RootPart.ApplyImpulse((vel * sceneObject.GetMass()), false); + sceneObject.Velocity = vel; + } + + return true; + } /// /// Add an object to the scene. This will both update the scene, and send information about the From a2113ecc71ea29aebb05c2aa676afc7ce05b9563 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Tue, 24 Aug 2010 21:01:37 -0700 Subject: [PATCH 07/10] Typo --- bin/Robust.HG.ini.example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/Robust.HG.ini.example b/bin/Robust.HG.ini.example index 122ba2e5f5..554d00f86b 100644 --- a/bin/Robust.HG.ini.example +++ b/bin/Robust.HG.ini.example @@ -100,7 +100,7 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003 [UserAccountService] ; for the server connector LocalServiceModule = "OpenSim.Services.UserAccountService.dll:UserAccountService" - ; Realm = "usersaccounts" + ; Realm = "useraccounts" ; These are for creating new accounts by the service AuthenticationService = "OpenSim.Services.AuthenticationService.dll:PasswordAuthenticationService" From 739eb14741151716bf1325c0d73a95e6ee8c148d Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Wed, 25 Aug 2010 23:04:12 +0200 Subject: [PATCH 08/10] Change some e.Message to e.ToString. Don't use e.Message, it doesn't carry any useful information. Error messages are useless without location information. It looks more elegant, but is totally pointless. --- .../Servers/HttpServer/SynchronousRestFormsRequester.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Framework/Servers/HttpServer/SynchronousRestFormsRequester.cs b/OpenSim/Framework/Servers/HttpServer/SynchronousRestFormsRequester.cs index b0cf34d16e..acf725abb2 100644 --- a/OpenSim/Framework/Servers/HttpServer/SynchronousRestFormsRequester.cs +++ b/OpenSim/Framework/Servers/HttpServer/SynchronousRestFormsRequester.cs @@ -81,7 +81,7 @@ namespace OpenSim.Framework.Servers.HttpServer } catch (Exception e) { - m_log.DebugFormat("[FORMS]: exception occured on sending request to {0}: {1}", requestUrl, e.Message); + m_log.DebugFormat("[FORMS]: exception occured on sending request to {0}: " + e.ToString(), requestUrl); } finally { @@ -112,7 +112,7 @@ namespace OpenSim.Framework.Servers.HttpServer } catch (Exception e) { - m_log.DebugFormat("[FORMS]: exception occured on receiving reply {0}", e.Message); + m_log.DebugFormat("[FORMS]: exception occured on receiving reply " + e.ToString()); } finally { From 604423d52bb66b1cc08adac557450addc7ebc94b Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Wed, 25 Aug 2010 23:11:00 +0200 Subject: [PATCH 09/10] Make scene object directories more robust and prevent deleted SOP's from sticking around --- OpenSim/Region/Framework/Scenes/Scene.cs | 1 - OpenSim/Region/Framework/Scenes/SceneGraph.cs | 46 ++++++++++++------- 2 files changed, 29 insertions(+), 18 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index b808c6d74c..f4cbe1f128 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -3159,7 +3159,6 @@ namespace OpenSim.Region.Framework.Scenes } m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode); - //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false)); //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true)); } diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 31faeec620..58a7661ab2 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -95,7 +95,6 @@ namespace OpenSim.Region.Framework.Scenes protected internal Dictionary SceneObjectGroupsByLocalID = new Dictionary(); protected internal Dictionary SceneObjectGroupsByFullID = new Dictionary(); - private readonly Object m_dictionary_lock = new Object(); private Object m_updateLock = new Object(); @@ -136,11 +135,10 @@ namespace OpenSim.Region.Framework.Scenes m_scenePresenceArray = newlist; } - lock (m_dictionary_lock) - { + lock (SceneObjectGroupsByFullID) SceneObjectGroupsByFullID.Clear(); + lock (SceneObjectGroupsByLocalID) SceneObjectGroupsByLocalID.Clear(); - } Entities.Clear(); } @@ -395,15 +393,17 @@ namespace OpenSim.Region.Framework.Scenes if (OnObjectCreate != null) OnObjectCreate(sceneObject); - lock (m_dictionary_lock) + lock (SceneObjectGroupsByFullID) { SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject; + foreach (SceneObjectPart part in sceneObject.Children.Values) + SceneObjectGroupsByFullID[part.UUID] = sceneObject; + } + lock (SceneObjectGroupsByLocalID) + { SceneObjectGroupsByLocalID[sceneObject.LocalId] = sceneObject; foreach (SceneObjectPart part in sceneObject.Children.Values) - { - SceneObjectGroupsByFullID[part.UUID] = sceneObject; SceneObjectGroupsByLocalID[part.LocalId] = sceneObject; - } } } @@ -418,24 +418,32 @@ namespace OpenSim.Region.Framework.Scenes { if (Entities.ContainsKey(uuid)) { + SceneObjectGroup grp = (SceneObjectGroup)Entities[uuid]; + if (!resultOfObjectLinked) { m_numPrim -= ((SceneObjectGroup) Entities[uuid]).Children.Count; - if ((((SceneObjectGroup)Entities[uuid]).RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics) - { - RemovePhysicalPrim(((SceneObjectGroup)Entities[uuid]).Children.Count); - } + if ((grp.RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics) + RemovePhysicalPrim(grp.Children.Count); } if (OnObjectRemove != null) OnObjectRemove(Entities[uuid]); - lock (m_dictionary_lock) + lock (SceneObjectGroupsByFullID) { - SceneObjectGroupsByFullID.Remove(uuid); - SceneObjectGroupsByLocalID.Remove(((SceneObjectGroup)Entities[uuid]).LocalId); + foreach (SceneObjectPart part in grp.Children.Values) + SceneObjectGroupsByFullID.Remove(part.UUID); + SceneObjectGroupsByFullID.Remove(grp.RootPart.UUID); } + lock (SceneObjectGroupsByLocalID) + { + foreach (SceneObjectPart part in grp.Children.Values) + SceneObjectGroupsByLocalID.Remove(part.LocalId); + SceneObjectGroupsByLocalID.Remove(grp.RootPart.LocalId); + } + Entities.Remove(uuid); //SceneObjectGroup part; //((part.RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics) @@ -860,7 +868,9 @@ namespace OpenSim.Region.Framework.Scenes { if (SceneObjectGroupsByLocalID.TryGetValue(localID, out sog)) { - return sog; + if (sog.HasChildPrim(localID)) + return sog; + SceneObjectGroupsByLocalID.Remove(localID); } } @@ -896,7 +906,9 @@ namespace OpenSim.Region.Framework.Scenes { if (SceneObjectGroupsByFullID.TryGetValue(fullID, out sog)) { - return sog; + if (sog.Children.ContainsKey(fullID)) + return sog; + SceneObjectGroupsByFullID.Remove(fullID); } } From 75e2a2b3ceeb67d3124bc8b4534b6927d288fd57 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Wed, 25 Aug 2010 23:34:39 +0200 Subject: [PATCH 10/10] Prevent an object disposed exception that made forms comms unreliable. After starting an asynchronous write, one should not close the channel it will be written to synchrnously, that leads to grief. --- .../Servers/HttpServer/SynchronousRestFormsRequester.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/OpenSim/Framework/Servers/HttpServer/SynchronousRestFormsRequester.cs b/OpenSim/Framework/Servers/HttpServer/SynchronousRestFormsRequester.cs index acf725abb2..b2c1c54954 100644 --- a/OpenSim/Framework/Servers/HttpServer/SynchronousRestFormsRequester.cs +++ b/OpenSim/Framework/Servers/HttpServer/SynchronousRestFormsRequester.cs @@ -85,8 +85,13 @@ namespace OpenSim.Framework.Servers.HttpServer } finally { - if (requestStream != null) - requestStream.Close(); + // If this is closed, it will be disposed internally, + // but the above write is asynchronous and may hit after + // we're through here. So the thread handling that will + // throw and put us back into the catch above. Isn't + // .NET great? + //if (requestStream != null) + // requestStream.Close(); // Let's not close this //buffer.Close();