diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs index c039b5a387..b5272ad151 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs @@ -46,6 +46,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + /// + /// Determine whether this archive will save assets. Default is true. + /// + public bool SaveAssets { get; set; } + /// /// Used to select all inventory nodes in a folder but not the folder itself /// @@ -112,6 +117,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver m_invPath = invPath; m_saveStream = saveStream; m_assetGatherer = new UuidGatherer(m_scene.AssetService); + + SaveAssets = true; } protected void ReceivedAllAssets(ICollection assetsFoundUuids, ICollection assetsNotFoundUuids) @@ -150,7 +157,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver string serialization = UserInventoryItemSerializer.Serialize(inventoryItem, options, userAccountService); m_archiveWriter.WriteFile(filename, serialization); - m_assetGatherer.GatherAssetUuids(inventoryItem.AssetID, (AssetType)inventoryItem.AssetType, m_assetUuids); + if (SaveAssets) + m_assetGatherer.GatherAssetUuids(inventoryItem.AssetID, (AssetType)inventoryItem.AssetType, m_assetUuids); } /// @@ -195,6 +203,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// public void Execute(Dictionary options, IUserAccountService userAccountService) { + if (options.ContainsKey("noassets") && (bool)options["noassets"]) + SaveAssets = false; + try { InventoryFolderBase inventoryFolder = null; @@ -285,12 +296,23 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver // Don't put all this profile information into the archive right now. //SaveUsers(); - - new AssetsRequest( - new AssetsArchiver(m_archiveWriter), - m_assetUuids, m_scene.AssetService, - m_scene.UserAccountService, m_scene.RegionInfo.ScopeID, - options, ReceivedAllAssets).Execute(); + + if (SaveAssets) + { + m_log.DebugFormat("[INVENTORY ARCHIVER]: Saving {0} assets for items", m_assetUuids.Count); + + new AssetsRequest( + new AssetsArchiver(m_archiveWriter), + m_assetUuids, m_scene.AssetService, + m_scene.UserAccountService, m_scene.RegionInfo.ScopeID, + options, ReceivedAllAssets).Execute(); + } + else + { + m_log.DebugFormat("[INVENTORY ARCHIVER]: Not saving assets since --noassets was specified"); + + ReceivedAllAssets(new List(), new List()); + } } catch (Exception) { @@ -387,19 +409,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// /// /// - public static string CreateControlFile(Dictionary options) + public string CreateControlFile(Dictionary options) { int majorVersion, minorVersion; if (options.ContainsKey("profile")) { majorVersion = 1; - minorVersion = 1; + minorVersion = 2; } else { majorVersion = 0; - minorVersion = 2; + minorVersion = 3; } m_log.InfoFormat("[INVENTORY ARCHIVER]: Creating version {0}.{1} IAR", majorVersion, minorVersion); @@ -411,6 +433,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver xtw.WriteStartElement("archive"); xtw.WriteAttributeString("major_version", majorVersion.ToString()); xtw.WriteAttributeString("minor_version", minorVersion.ToString()); + + xtw.WriteElementString("assets_included", SaveAssets.ToString()); + xtw.WriteEndElement(); xtw.Flush(); diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs index 576a154719..e0b02aac46 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs @@ -122,7 +122,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver scene.AddCommand( this, "save iar", - "save iar [--p|-profile=] [] [--v|-verbose]", + "save iar [--p|-profile=] [--noassets] [] [--v|-verbose]", "Save user inventory archive (IAR).", " is the user's first name." + Environment.NewLine + " is the user's last name." + Environment.NewLine @@ -130,6 +130,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver + "-p|--profile= adds the url of the profile service to the saved user information." + Environment.NewLine + "-c|--creators preserves information about foreign creators." + Environment.NewLine + "-v|--verbose extra debug messages." + Environment.NewLine + + "--noassets stops assets being saved to the IAR." + " is the filesystem path at which to save the IAR." + string.Format(" If this is not given then the filename {0} in the current directory is used", DEFAULT_INV_BACKUP_FILENAME), HandleSaveInvConsoleCommand); @@ -398,6 +399,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver ops.Add("p|profile=", delegate(string v) { options["profile"] = v; }); ops.Add("v|verbose", delegate(string v) { options["verbose"] = v; }); ops.Add("c|creators", delegate(string v) { options["creators"] = v; }); + ops.Add("noassets", delegate(string v) { options["noassets"] = v != null; }); List mainParams = ops.Parse(cmdparams); @@ -406,7 +408,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver if (mainParams.Count < 6) { m_log.Error( - "[INVENTORY ARCHIVER]: usage is save iar [--p|-profile=] []"); + "[INVENTORY ARCHIVER]: usage is save iar [--p|-profile=] [--noassets] []"); return; } @@ -423,16 +425,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver m_log.InfoFormat( "[INVENTORY ARCHIVER]: Saving archive {0} using inventory path {1} for {2} {3}", savePath, invPath, firstName, lastName); - + + lock (m_pendingConsoleSaves) + m_pendingConsoleSaves.Add(id); + ArchiveInventory(id, firstName, lastName, invPath, pass, savePath, options); } catch (InventoryArchiverException e) { m_log.ErrorFormat("[INVENTORY ARCHIVER]: {0}", e.Message); } - - lock (m_pendingConsoleSaves) - m_pendingConsoleSaves.Add(id); } private void SaveInvConsoleCommandCompleted( diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs index d97311ab2b..ae3ab21b18 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs @@ -123,11 +123,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests } /// - /// Test saving a single inventory item to a V0.1 OpenSim Inventory Archive + /// Test saving a single inventory item to an IAR /// (subject to change since there is no fixed format yet). /// [Test] - public void TestSaveItemToIarV0_1() + public void TestSaveItemToIar() { TestHelper.InMethod(); // log4net.Config.XmlConfigurator.Configure(); @@ -211,6 +211,106 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests } } +// Assert.That(gotControlFile, Is.True, "No control file in archive"); + Assert.That(gotObject1File, Is.True, "No item1 file in archive"); +// Assert.That(gotObject2File, Is.True, "No object2 file in archive"); + + // TODO: Test presence of more files and contents of files. + } + + /// + /// Test saving a single inventory item to an IAR without its asset + /// + [Test] + public void TestSaveItemToIarNoAssets() + { + TestHelper.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + // Create user + string userFirstName = "Jock"; + string userLastName = "Stirrup"; + string userPassword = "troll"; + UUID userId = UUID.Parse("00000000-0000-0000-0000-000000000020"); + UserAccountHelpers.CreateUserWithInventory(m_scene, userFirstName, userLastName, userId, userPassword); + + // Create asset + UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000040"); + SceneObjectGroup object1 = SceneSetupHelpers.CreateSceneObject(1, ownerId, "My Little Dog Object", 0x50); + + UUID asset1Id = UUID.Parse("00000000-0000-0000-0000-000000000060"); + AssetBase asset1 = AssetHelpers.CreateAsset(asset1Id, object1); + m_scene.AssetService.Store(asset1); + + // Create item + UUID item1Id = UUID.Parse("00000000-0000-0000-0000-000000000080"); + string item1Name = "My Little Dog"; + InventoryItemBase item1 = new InventoryItemBase(); + item1.Name = item1Name; + item1.AssetID = asset1.FullID; + item1.ID = item1Id; + InventoryFolderBase objsFolder + = InventoryArchiveUtils.FindFolderByPath(m_scene.InventoryService, userId, "Objects")[0]; + item1.Folder = objsFolder.ID; + m_scene.AddInventoryItem(item1); + + MemoryStream archiveWriteStream = new MemoryStream(); + + Dictionary options = new Dictionary(); + options.Add("noassets", true); + + // When we're not saving assets, archiving is being done synchronously. + m_archiverModule.ArchiveInventory( + Guid.NewGuid(), userFirstName, userLastName, "Objects/" + item1Name, userPassword, archiveWriteStream, options); + + byte[] archive = archiveWriteStream.ToArray(); + MemoryStream archiveReadStream = new MemoryStream(archive); + TarArchiveReader tar = new TarArchiveReader(archiveReadStream); + + //bool gotControlFile = false; + bool gotObject1File = false; + //bool gotObject2File = false; + string expectedObject1FileName = InventoryArchiveWriteRequest.CreateArchiveItemName(item1); + string expectedObject1FilePath = string.Format( + "{0}{1}", + ArchiveConstants.INVENTORY_PATH, + expectedObject1FileName); + + string filePath; + TarArchiveReader.TarEntryType tarEntryType; + +// Console.WriteLine("Reading archive"); + + while (tar.ReadEntry(out filePath, out tarEntryType) != null) + { + Console.WriteLine("Got {0}", filePath); + +// if (ArchiveConstants.CONTROL_FILE_PATH == filePath) +// { +// gotControlFile = true; +// } + + if (filePath.StartsWith(ArchiveConstants.INVENTORY_PATH) && filePath.EndsWith(".xml")) + { +// string fileName = filePath.Remove(0, "Objects/".Length); +// +// if (fileName.StartsWith(part1.Name)) +// { + Assert.That(expectedObject1FilePath, Is.EqualTo(filePath)); + gotObject1File = true; +// } +// else if (fileName.StartsWith(part2.Name)) +// { +// Assert.That(fileName, Is.EqualTo(expectedObject2FileName)); +// gotObject2File = true; +// } + } + else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH)) + { + Assert.Fail("Found asset path in TestSaveItemToIarNoAssets()"); + } + } + // Assert.That(gotControlFile, Is.True, "No control file in archive"); Assert.That(gotObject1File, Is.True, "No item1 file in archive"); // Assert.That(gotObject2File, Is.True, "No object2 file in archive"); diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs index 3d073bf51b..10a83ee826 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs @@ -61,7 +61,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver public static int MAX_MAJOR_VERSION = 0; /// - /// Determine whether this oar will save assets. Default is true. + /// Determine whether this archive will save assets. Default is true. /// public bool SaveAssets { get; set; }