From b52ac542ade6af9ad404dcebf68be3bef769b0e1 Mon Sep 17 00:00:00 2001 From: Justin Clarke Casey Date: Wed, 4 Mar 2009 20:31:03 +0000 Subject: * Add the abilty to load and save iar item nodes where folders have identical names --- .../Archiver/InventoryArchiveConstants.cs | 5 ++ .../Archiver/InventoryArchiveReadRequest.cs | 91 ++++++++++++++++++---- .../Archiver/InventoryArchiveWriteRequest.cs | 55 +++++++++---- .../Archiver/Tests/InventoryArchiverTests.cs | 12 ++- 4 files changed, 132 insertions(+), 31 deletions(-) (limited to 'OpenSim/Region/CoreModules/Avatar') diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveConstants.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveConstants.cs index b274af2..e2bce16 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveConstants.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveConstants.cs @@ -51,6 +51,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver public static readonly string ASSET_EXTENSION_SEPARATOR = "_"; /// + /// Used to separate components in an inventory node name + /// + public static readonly string INVENTORY_NODE_NAME_COMPONENT_SEPARATOR = "__"; + + /// /// Extensions used for asset types in the archive /// public static readonly IDictionary ASSET_TYPE_TO_EXTENSION = new Dictionary(); diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs index fc63957..4a681bc 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs @@ -85,7 +85,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver if (contents.Equals("")) return null; - reader.ReadStartElement("InventoryObject"); + reader.ReadStartElement("InventoryItem"); reader.ReadStartElement("Name"); item.Name = reader.ReadString(); reader.ReadEndElement(); @@ -138,10 +138,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver reader.ReadStartElement("GroupOwned"); item.GroupOwned = Convert.ToBoolean(reader.ReadString()); reader.ReadEndElement(); - //reader.ReadStartElement("ParentFolderID"); - //item.Folder = UUID.Parse(reader.ReadString()); - //reader.ReadEndElement(); - //reader.ReadEndElement(); return item; } @@ -187,13 +183,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver if (null == rootDestinationFolder) { - // TODO: Later on, automatically create this folder if it does not exist + // Possibly provide an option later on to automatically create this folder if it does not exist m_log.ErrorFormat("[INVENTORY ARCHIVER]: Inventory path {0} does not exist", m_invPath); return nodesLoaded; } archive = new TarArchiveReader(m_loadStream); + + // In order to load identically named folders, we need to keep track of the folders that we have already + // created + Dictionary foldersCreated = new Dictionary(); byte[] data; TarArchiveReader.TarEntryType entryType; @@ -222,12 +222,72 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver item.Creator = m_userInfo.UserProfile.ID; item.Owner = m_userInfo.UserProfile.ID; - filePath = filePath.Substring(InventoryArchiveConstants.INVENTORY_PATH.Length); - filePath = filePath.Remove(filePath.LastIndexOf("/")); + string fsPath = filePath.Substring(InventoryArchiveConstants.INVENTORY_PATH.Length); + fsPath = fsPath.Remove(fsPath.LastIndexOf("/") + 1); + string originalFsPath = fsPath; + + m_log.DebugFormat("[INVENTORY ARCHIVER]: Loading to folder {0}", fsPath); - m_log.DebugFormat("[INVENTORY ARCHIVER]: Loading to file path {0}", filePath); + InventoryFolderImpl foundFolder = null; + while (null == foundFolder && fsPath.Length > 0) + { + if (foldersCreated.ContainsKey(fsPath)) + { + m_log.DebugFormat("[INVENTORY ARCHIVER]: Found previously created fs path {0}", fsPath); + foundFolder = foldersCreated[fsPath]; + } + else + { + // Don't include the last slash + int penultimateSlashIndex = fsPath.LastIndexOf("/", fsPath.Length - 2); + + if (penultimateSlashIndex >= 0) + { + fsPath = fsPath.Remove(penultimateSlashIndex + 1); + } + else + { + m_log.DebugFormat( + "[INVENTORY ARCHIVER]: Found no previously created fs path for {0}", + originalFsPath); + fsPath = string.Empty; + foundFolder = rootDestinationFolder; + } + } + } - string[] rawFolders = filePath.Split(new char[] { '/' }); + string fsPathSectionToCreate = originalFsPath.Substring(fsPath.Length); + string[] rawDirsToCreate + = fsPathSectionToCreate.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries); + int i = 0; + + while (i < rawDirsToCreate.Length) + { + m_log.DebugFormat("[INVENTORY ARCHIVER]: Creating folder {0}", rawDirsToCreate[i]); + + int identicalNameIdentifierIndex + = rawDirsToCreate[i].LastIndexOf( + InventoryArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR); + string folderName = rawDirsToCreate[i].Remove(identicalNameIdentifierIndex); + + UUID newFolderId = UUID.Random(); + m_userInfo.CreateFolder( + folderName, newFolderId, (ushort)AssetType.Folder, foundFolder.ID); + foundFolder = foundFolder.GetChildFolder(newFolderId); + + // Record that we have now created this folder + fsPath += rawDirsToCreate[i] + "/"; + m_log.DebugFormat("[INVENTORY ARCHIVER]: Recording creation of fs path {0}", fsPath); + foldersCreated[fsPath] = foundFolder; + + if (0 == i) + nodesLoaded.Add(foundFolder); + + i++; + } + + /* + string[] rawFolders = filePath.Split(new char[] { '/' }); // Find the folders that do exist along the path given int i = 0; @@ -257,16 +317,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver m_userInfo.CreateFolder( rawFolders[i++], newFolderId, (ushort)AssetType.Folder, foundFolder.ID); foundFolder = foundFolder.GetChildFolder(newFolderId); - } + } + */ // Reset folder ID to the one in which we want to load it item.Folder = foundFolder.ID; - - //item.Folder = rootDestinationFolder.ID; m_userInfo.AddItem(item); successfulItemRestores++; - nodesLoaded.Add(item); + + // If we're loading an item directly into the given destination folder then we need to record + // it separately from any loaded root folders + if (rootDestinationFolder == foundFolder) + nodesLoaded.Add(item); } } } diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs index 2b071f0..357ed40 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs @@ -106,14 +106,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver m_module.TriggerInventoryArchiveSaved(succeeded, m_userInfo, m_invPath, m_saveStream, reportedException); } - protected void saveInvItem(InventoryItemBase inventoryItem, string path) + protected void SaveInvItem(InventoryItemBase inventoryItem, string path) { string filename = string.Format("{0}{1}_{2}.xml", path, inventoryItem.Name, inventoryItem.ID); StringWriter sw = new StringWriter(); XmlTextWriter writer = new XmlTextWriter(sw); writer.Formatting = Formatting.Indented; - writer.WriteStartElement("InventoryObject"); + writer.WriteStartElement("InventoryItem"); + writer.WriteStartElement("Name"); writer.WriteString(inventoryItem.Name); writer.WriteEndElement(); @@ -168,9 +169,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver writer.WriteStartElement("GroupOwned"); writer.WriteString(inventoryItem.GroupOwned.ToString()); writer.WriteEndElement(); - writer.WriteStartElement("ParentFolderID"); - writer.WriteString(inventoryItem.Folder.ToString()); - writer.WriteEndElement(); + writer.WriteEndElement(); archive.AddFile(filename, sw.ToString()); @@ -178,20 +177,48 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver m_assetGatherer.GatherAssetUuids(inventoryItem.AssetID, (AssetType)inventoryItem.AssetType, assetUuids); } - protected void saveInvDir(InventoryFolderImpl inventoryFolder, string path) + protected void SaveInvDir(InventoryFolderImpl inventoryFolder, string path) { - List inventories = inventoryFolder.RequestListOfFolderImpls(); - List items = inventoryFolder.RequestListOfItems(); - string newPath = path + inventoryFolder.Name + InventoryFolderImpl.PATH_DELIMITER; - archive.AddDir(newPath); + path += + string.Format( + "{0}{1}{2}/", + inventoryFolder.Name, + InventoryArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR, + inventoryFolder.ID); + archive.AddDir(path); + + List childFolders = inventoryFolder.RequestListOfFolderImpls(); + List items = inventoryFolder.RequestListOfItems(); + + /* + Dictionary identicalFolderNames = new Dictionary(); foreach (InventoryFolderImpl folder in inventories) { - saveInvDir(folder, newPath); + + if (!identicalFolderNames.ContainsKey(folder.Name)) + identicalFolderNames[folder.Name] = 0; + else + identicalFolderNames[folder.Name] = identicalFolderNames[folder.Name]++; + + int folderNameNumber = identicalFolderName[folder.Name]; + + SaveInvDir( + folder, + string.Format( + "{0}{1}{2}/", + path, InventoryArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR, folderNameNumber)); + } + */ + + foreach (InventoryFolderImpl childFolder in childFolders) + { + SaveInvDir(childFolder, path); } + foreach (InventoryItemBase item in items) { - saveInvItem(item, newPath); + SaveInvItem(item, path); } } @@ -270,7 +297,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver inventoryItem.Name, inventoryItem.ID, m_invPath); //get and export item info - saveInvItem(inventoryItem, m_invPath); + SaveInvItem(inventoryItem, m_invPath); } } else @@ -280,7 +307,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver inventoryFolder.Name, inventoryFolder.ID, m_invPath); //recurse through all dirs getting dirs and files - saveInvDir(inventoryFolder, InventoryArchiveConstants.INVENTORY_PATH); + SaveInvDir(inventoryFolder, InventoryArchiveConstants.INVENTORY_PATH); } new AssetsRequest(assetUuids.Keys, m_module.CommsManager.AssetCache, ReceivedAllAssets).Execute(); diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs index cb613f7..5cc0340 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs @@ -124,15 +124,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests MemoryStream archiveReadStream = new MemoryStream(archive); TarArchiveReader tar = new TarArchiveReader(archiveReadStream); + InventoryFolderImpl objectsFolder = userInfo.RootFolder.FindFolderByPath("Objects"); + //bool gotControlFile = false; bool gotObject1File = false; //bool gotObject2File = false; string expectedObject1FilePath = string.Format( - "{0}{1}{2}_{3}.xml", + "{0}{1}/{2}_{3}.xml", InventoryArchiveConstants.INVENTORY_PATH, - "Objects/", + string.Format( + "Objects{0}{1}", InventoryArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR, objectsFolder.ID), item1.Name, item1Id); + /* string expectedObject2FileName = string.Format( "{0}_{1:000}-{2:000}-{3:000}__{4}.xml", @@ -146,6 +150,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests while (tar.ReadEntry(out filePath, out tarEntryType) != null) { + Console.WriteLine("Got {0}", filePath); + /* if (ArchiveConstants.CONTROL_FILE_PATH == filePath) { @@ -153,7 +159,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests } */ if (filePath.StartsWith(InventoryArchiveConstants.INVENTORY_PATH) && filePath.EndsWith(".xml")) - { + { //string fileName = filePath.Remove(0, "Objects/".Length); //if (fileName.StartsWith(part1.Name)) -- cgit v1.1