public static FindFolderByPath ( IInventoryService inventoryService, |
||
inventoryService | IInventoryService | /// Inventory service to query /// |
startFolder | /// The folder from which the path starts /// | |
path | string | /// The path to the required folder. /// It this is empty or consists only of the PATH_DELIMTER then this folder itself is returned. /// |
Результат | List |
/// <summary> /// Resolve a destination folder /// </summary> /// We require here a root destination folder (usually the root of the user's inventory) and the archive /// path. We also pass in a list of previously resolved folders in case we've found this one previously. /// <param name="archivePath"> /// The item archive path to resolve. The portion of the path passed back is that /// which corresponds to the resolved destination folder. /// </param> /// <param name="rootDestFolder"> /// The root folder for the inventory load /// </param> /// <param name="resolvedFolders"> /// The folders that we have resolved so far for a given archive path. /// </param> /// <returns> /// The folder in the user's inventory that matches best the archive path given. If no such folder was found /// then the passed in root destination folder is returned. /// </returns> protected InventoryFolderBase ResolveDestinationFolder( InventoryFolderBase rootDestFolder, ref string archivePath, ref Dictionary <string, InventoryFolderBase> resolvedFolders) { //string originalArchivePath = archivePath; while (archivePath.Length > 0) { //MainConsole.Instance.DebugFormat("[Inventory Archiver]: Trying to resolve destination folder {0}", archivePath); if (resolvedFolders.ContainsKey(archivePath)) { //MainConsole.Instance.DebugFormat( // "[Inventory Archiver]: Found previously created folder from archive path {0}", archivePath); return(resolvedFolders [archivePath]); } if (m_merge) { // TODO: Using m_invPath is totally wrong - what we need to do is strip the uuid from the // iar name and try to find that instead. string plainPath = ArchiveConstants.ExtractPlainPathFromIarPath(archivePath); List <InventoryFolderBase> folderCandidates = InventoryArchiveUtils.FindFolderByPath(m_inventoryService, m_userInfo.PrincipalID, plainPath); if (folderCandidates.Count != 0) { InventoryFolderBase destFolder = folderCandidates [0]; resolvedFolders [archivePath] = destFolder; return(destFolder); } } // Don't include the last slash so find the penultimate one int penultimateSlashIndex = archivePath.LastIndexOf("/", archivePath.Length - 2, StringComparison.Ordinal); if (penultimateSlashIndex >= 0) { // Remove the last section of path so that we can see if we've already resolved the parent archivePath = archivePath.Remove(penultimateSlashIndex + 1); } else { //MainConsole.Instance.DebugFormat( // "[Inventory Archiver]: Found no previously created folder for archive path {0}", originalArchivePath); archivePath = string.Empty; return(rootDestFolder); } } return(rootDestFolder); }
/// <summary> /// Execute the request /// </summary> /// <returns> /// A list of the inventory nodes loaded. If folders were loaded then only the root folders are /// returned /// </returns> public HashSet <InventoryNodeBase> Execute(bool loadAll) { if (m_loadStream == null) { return(new HashSet <InventoryNodeBase>()); } try { string filePath = "ERROR"; int successfulAssetRestores = 0; int failedAssetRestores = 0; int successfulItemRestores = 0; HashSet <InventoryNodeBase> loadedNodes = loadAll ? new HashSet <InventoryNodeBase>() : null; List <InventoryFolderBase> folderCandidates = InventoryArchiveUtils.FindFolderByPath(m_inventoryService, m_userInfo.PrincipalID, m_invPath); if (folderCandidates.Count == 0) { // try and create requested folder var rootFolder = m_inventoryService.GetRootFolder(m_userInfo.PrincipalID); InventoryFolderBase iarImportFolder = new InventoryFolderBase(); iarImportFolder.ID = UUID.Random(); iarImportFolder.Name = m_invPath; // the path iarImportFolder.Owner = m_userInfo.PrincipalID; // owner iarImportFolder.ParentID = rootFolder.ID; // the root folder iarImportFolder.Type = -1; // user defined folder iarImportFolder.Version = 1; // initial version m_inventoryService.AddFolder(iarImportFolder); // ensure that it now exists... folderCandidates = InventoryArchiveUtils.FindFolderByPath(m_inventoryService, m_userInfo.PrincipalID, m_invPath); if (folderCandidates.Count == 0) { MainConsole.Instance.ErrorFormat("[INVENTORY ARCHIVER]: Unable to create Inventory path {0}", m_invPath); return(loadedNodes); } } // we have the base folder... do it... InventoryFolderBase rootDestinationFolder = folderCandidates[0]; archive = new TarArchiveReader(m_loadStream); // In order to load identically named folders, we need to keep track of the folders that we have already // resolved Dictionary <string, InventoryFolderBase> resolvedFolders = new Dictionary <string, InventoryFolderBase>(); MainConsole.Instance.Info("[ARCHIVER]: Commencing load from archive"); int ticker = 0; byte[] data; TarArchiveReader.TarEntryType entryType; while ((data = archive.ReadEntry(out filePath, out entryType)) != null) { if (TarArchiveReader.TarEntryType.TYPE_NORMAL_FILE == entryType) { var fName = Path.GetFileName(filePath); if (fName.StartsWith(".")) // ignore hidden files { continue; } } ticker++; if (ticker % 5 == 0) { MainConsole.Instance.Ticker(); } if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH)) { if (LoadAsset(filePath, data)) { successfulAssetRestores++; } else { failedAssetRestores++; } if ((successfulAssetRestores) % 50 == 0) { MainConsole.Instance.InfoFormat( " [INVENTORY ARCHIVER]: Loaded {0} assets...", successfulAssetRestores); } } else if (filePath.StartsWith(ArchiveConstants.INVENTORY_PATH)) { filePath = filePath.Substring(ArchiveConstants.INVENTORY_PATH.Length); // Trim off the file portion if we aren't already dealing with a directory path if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY != entryType) { filePath = filePath.Remove(filePath.LastIndexOf("/") + 1); } InventoryFolderBase foundFolder = ReplicateArchivePathToUserInventory( filePath, rootDestinationFolder, ref resolvedFolders, ref loadedNodes); if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY != entryType) { InventoryItemBase item = LoadItem(data, foundFolder); if (item != null) { successfulItemRestores++; if ((successfulItemRestores) % 50 == 0) { MainConsole.Instance.InfoFormat( "[INVENTORY ARCHIVER]: Restored {0} items...", successfulItemRestores); } // If we aren't loading the folder containing the item then well need to update the // viewer separately for that item. if (loadAll && !loadedNodes.Contains(foundFolder)) { loadedNodes.Add(item); } } item = null; } } else if (filePath == ArchiveConstants.CONTROL_FILE_PATH) { LoadControlFile(data); } data = null; } MainConsole.Instance.CleanInfo(""); MainConsole.Instance.Info("[INVENTORY ARCHIVER]: Saving loaded inventory items"); ticker = 0; int successfulItemLoaded = 0; foreach (InventoryItemBase item in itemsSavedOff) { ticker++; if (ticker % 5 == 0) { MainConsole.Instance.Ticker(); } AddInventoryItem(item); successfulItemLoaded++; if ((successfulItemLoaded) % 50 == 0) { MainConsole.Instance.InfoFormat( "[INVENTORY ARCHIVER]: Loaded {0} items of {1}...", successfulItemLoaded, itemsSavedOff.Count); } } itemsSavedOff.Clear(); assets2Save.Clear(); MainConsole.Instance.CleanInfo(""); MainConsole.Instance.InfoFormat( "[INVENTORY ARCHIVER]: Successfully loaded {0} assets with {1} failures", successfulAssetRestores, failedAssetRestores); MainConsole.Instance.InfoFormat("[INVENTORY ARCHIVER]: Successfully loaded {0} items", successfulItemRestores); return(loadedNodes); } finally { m_loadStream.Close(); } }
/// <summary> /// Execute the inventory write request /// </summary> public void Execute() { try { InventoryFolderBase inventoryFolder = null; InventoryItemBase inventoryItem = null; InventoryFolderBase rootFolder = m_inventoryService.GetRootFolder(m_userInfo.PrincipalID); if (m_defaultFolderToSave != null) { rootFolder = m_defaultFolderToSave; } bool saveFolderContentsOnly = false; // Eliminate double slashes and any leading / on the path. string[] components = m_invPath.Split( new[] { InventoryFolderImpl.PATH_DELIMITER }, StringSplitOptions.RemoveEmptyEntries); int maxComponentIndex = components.Length - 1; // If the path terminates with a STAR then later on we want to archive all nodes in the folder but not the // folder itself. This may get more sophisicated later on if (maxComponentIndex >= 0 && components[maxComponentIndex] == STAR_WILDCARD) { saveFolderContentsOnly = true; maxComponentIndex--; } else if (maxComponentIndex == -1) { // If the user has just specified "/", then don't save the root "My Inventory" folder. This is // more intuitive then requiring the user to specify "/*" for this. // 20141119-greythane- This breaks saving default inventory // saveFolderContentsOnly = true; } m_invPath = String.Empty; for (int i = 0; i <= maxComponentIndex; i++) { m_invPath += components[i] + InventoryFolderImpl.PATH_DELIMITER; } // Annoyingly Split actually returns the original string if the input string consists only of delimiters // Therefore if we still start with a / after the split, then we need the root folder if (m_invPath.Length == 0) { inventoryFolder = rootFolder; } else { m_invPath = m_invPath.Remove(m_invPath.LastIndexOf(InventoryFolderImpl.PATH_DELIMITER)); List <InventoryFolderBase> candidateFolders = InventoryArchiveUtils.FindFolderByPath(m_inventoryService, rootFolder, m_invPath); if (candidateFolders.Count > 0) { inventoryFolder = candidateFolders[0]; } } // The path may point to an item instead if (inventoryFolder == null) { inventoryItem = InventoryArchiveUtils.FindItemByPath(m_inventoryService, rootFolder, m_invPath); } if (null == inventoryFolder && null == inventoryItem) { // We couldn't find the path indicated string errorMessage = string.Format("Aborted save. Could not find inventory path {0}", m_invPath); Exception e = new InventoryArchiverException(errorMessage); if (m_module != null) { m_module.TriggerInventoryArchiveSaved(m_id, false, m_userInfo, m_invPath, m_saveStream, e); } throw e; } m_archiveWriter = new TarArchiveWriter(m_saveStream); if (inventoryFolder != null) { MainConsole.Instance.DebugFormat( "[INVENTORY ARCHIVER]: Found folder {0} {1} at {2}", inventoryFolder.Name, inventoryFolder.ID, m_invPath == String.Empty ? InventoryFolderImpl.PATH_DELIMITER : m_invPath); //recurse through all dirs getting dirs and files SaveInvFolder(inventoryFolder, ArchiveConstants.INVENTORY_PATH, !saveFolderContentsOnly); } else if (inventoryItem != null) { MainConsole.Instance.DebugFormat( "[INVENTORY ARCHIVER]: Found item {0} {1} at {2}", inventoryItem.Name, inventoryItem.ID, m_invPath); SaveInvItem(inventoryItem, ArchiveConstants.INVENTORY_PATH); } } catch (Exception) { m_saveStream.Close(); throw; } if (m_saveAssets) { foreach (AssetBase asset in m_assetsToAdd) { m_assetUuids[asset.ID] = (AssetType)asset.Type; } new AssetsRequest( new AssetsArchiver(m_archiveWriter), m_assetUuids, m_assetService, ReceivedAllAssets).Execute(); } else { MainConsole.Instance.Debug("[INVENTORY ARCHIVER]: Save Complete"); m_archiveWriter.Close(); } }