From 8c10cb5ffe783d457184923d32e8baea5321ed1d Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 14 Jul 2010 20:43:35 +0100 Subject: improve closing of load/save iar streams in the event of a problem --- .../Archiver/InventoryArchiveReadRequest.cs | 80 ++++++------ .../Archiver/InventoryArchiveWriteRequest.cs | 139 ++++++++++----------- .../Archiver/InventoryArchiverException.cs | 40 ++++++ .../Inventory/Archiver/InventoryArchiverModule.cs | 111 +++++++++------- 4 files changed, 213 insertions(+), 157 deletions(-) create mode 100644 OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverException.cs (limited to 'OpenSim/Region/CoreModules') diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs index c8697fe..31dfe14 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs @@ -93,37 +93,37 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// public List Execute() { - string filePath = "ERROR"; - int successfulAssetRestores = 0; - int failedAssetRestores = 0; - int successfulItemRestores = 0; - - List loadedNodes = new List(); - - List folderCandidates - = InventoryArchiveUtils.FindFolderByPath( - m_scene.InventoryService, m_userInfo.PrincipalID, m_invPath); - - if (folderCandidates.Count == 0) - { - // 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 loadedNodes; - } - - 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 resolvedFolders = new Dictionary(); - - byte[] data; - TarArchiveReader.TarEntryType entryType; - try { + string filePath = "ERROR"; + int successfulAssetRestores = 0; + int failedAssetRestores = 0; + int successfulItemRestores = 0; + + List loadedNodes = new List(); + + List folderCandidates + = InventoryArchiveUtils.FindFolderByPath( + m_scene.InventoryService, m_userInfo.PrincipalID, m_invPath); + + if (folderCandidates.Count == 0) + { + // 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 loadedNodes; + } + + 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 resolvedFolders = new Dictionary(); + + byte[] data; + TarArchiveReader.TarEntryType entryType; + while ((data = archive.ReadEntry(out filePath, out entryType)) != null) { if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH)) @@ -166,18 +166,20 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver } } } + + archive.Close(); + + m_log.DebugFormat( + "[INVENTORY ARCHIVER]: Successfully loaded {0} assets with {1} failures", + successfulAssetRestores, failedAssetRestores); + m_log.InfoFormat("[INVENTORY ARCHIVER]: Successfully loaded {0} items", successfulItemRestores); + + return loadedNodes; } finally { - archive.Close(); - } - - m_log.DebugFormat( - "[INVENTORY ARCHIVER]: Successfully loaded {0} assets with {1} failures", - successfulAssetRestores, failedAssetRestores); - m_log.InfoFormat("[INVENTORY ARCHIVER]: Successfully loaded {0} items", successfulItemRestores); - - return loadedNodes; + m_loadStream.Close(); + } } public void Close() @@ -247,7 +249,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver ref string archivePath, Dictionary resolvedFolders) { - string originalArchivePath = archivePath; +// string originalArchivePath = archivePath; InventoryFolderBase destFolder = null; diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs index 2c2724e..25a78ff 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs @@ -119,22 +119,24 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver protected void ReceivedAllAssets(ICollection assetsFoundUuids, ICollection assetsNotFoundUuids) { Exception reportedException = null; - bool succeeded = true; - + bool succeeded = true; + try { // We're almost done. Just need to write out the control file now m_archiveWriter.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, Create0p1ControlFile()); m_log.InfoFormat("[ARCHIVER]: Added control file to archive."); - m_archiveWriter.Close(); } catch (Exception e) { - m_saveStream.Close(); reportedException = e; succeeded = false; } + finally + { + m_saveStream.Close(); + } m_module.TriggerInventoryArchiveSaved( m_id, succeeded, m_userInfo, m_invPath, m_saveStream, reportedException); @@ -213,70 +215,68 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// public void Execute() { - InventoryFolderBase inventoryFolder = null; - InventoryItemBase inventoryItem = null; - InventoryFolderBase rootFolder = m_scene.InventoryService.GetRootFolder(m_userInfo.PrincipalID); - - bool foundStar = false; - - // Eliminate double slashes and any leading / on the path. - string[] components - = m_invPath.Split( - new string[] { 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) - { - foundStar = true; - maxComponentIndex--; - } - - 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 candidateFolders - = InventoryArchiveUtils.FindFolderByPath(m_scene.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_scene.InventoryService, rootFolder, m_invPath); - //inventoryItem = m_userInfo.RootFolder.FindItemByPath(m_invPath); - } - - if (null == inventoryFolder && null == inventoryItem) + try { - // We couldn't find the path indicated - string errorMessage = string.Format("Aborted save. Could not find inventory path {0}", m_invPath); - m_log.ErrorFormat("[INVENTORY ARCHIVER]: {0}", errorMessage); - m_module.TriggerInventoryArchiveSaved( - m_id, false, m_userInfo, m_invPath, m_saveStream, - new Exception(errorMessage)); - return; - } + InventoryFolderBase inventoryFolder = null; + InventoryItemBase inventoryItem = null; + InventoryFolderBase rootFolder = m_scene.InventoryService.GetRootFolder(m_userInfo.PrincipalID); + + bool foundStar = false; + + // Eliminate double slashes and any leading / on the path. + string[] components + = m_invPath.Split( + new string[] { 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) + { + foundStar = true; + maxComponentIndex--; + } + + 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 candidateFolders + = InventoryArchiveUtils.FindFolderByPath(m_scene.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_scene.InventoryService, rootFolder, m_invPath); + //inventoryItem = m_userInfo.RootFolder.FindItemByPath(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); + m_module.TriggerInventoryArchiveSaved(m_id, false, m_userInfo, m_invPath, m_saveStream, e); + throw e; + } - m_archiveWriter = new TarArchiveWriter(m_saveStream); + m_archiveWriter = new TarArchiveWriter(m_saveStream); - try - { if (inventoryFolder != null) { m_log.DebugFormat( @@ -297,16 +297,15 @@ 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, ReceivedAllAssets).Execute(); } catch (Exception) { - m_archiveWriter.Close(); + m_saveStream.Close(); throw; } - - new AssetsRequest( - new AssetsArchiver(m_archiveWriter), m_assetUuids, - m_scene.AssetService, ReceivedAllAssets).Execute(); } /// diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverException.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverException.cs new file mode 100644 index 0000000..e07e2ca --- /dev/null +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverException.cs @@ -0,0 +1,40 @@ +/* + * 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; + +namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver +{ + /// + /// Signals an inventory archiving problem + /// + public class InventoryArchiverException : Exception + { + public InventoryArchiverException(string message) : base(message) {} + public InventoryArchiverException(string message, Exception e) : base(message, e) {} + } +} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs index cfefbe9..f7a2b09 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs @@ -322,34 +322,41 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// protected void HandleLoadInvConsoleCommand(string module, string[] cmdparams) { - m_log.Info("[INVENTORY ARCHIVER]: PLEASE NOTE THAT THIS FACILITY IS EXPERIMENTAL. BUG REPORTS WELCOME."); - - Dictionary options = new Dictionary(); - OptionSet optionSet = new OptionSet().Add("m|merge", delegate (string v) { options["merge"] = v != null; }); - - List mainParams = optionSet.Parse(cmdparams); - - if (mainParams.Count < 6) - { - m_log.Error( - "[INVENTORY ARCHIVER]: usage is load iar []"); - return; - } - - string firstName = mainParams[2]; - string lastName = mainParams[3]; - string invPath = mainParams[4]; - string pass = mainParams[5]; - string loadPath = (mainParams.Count > 6 ? mainParams[6] : DEFAULT_INV_BACKUP_FILENAME); - - m_log.InfoFormat( - "[INVENTORY ARCHIVER]: Loading archive {0} to inventory path {1} for {2} {3}", - loadPath, invPath, firstName, lastName); - - if (DearchiveInventory(firstName, lastName, invPath, pass, loadPath, options)) + try + { + m_log.Info("[INVENTORY ARCHIVER]: PLEASE NOTE THAT THIS FACILITY IS EXPERIMENTAL. BUG REPORTS WELCOME."); + + Dictionary options = new Dictionary(); + OptionSet optionSet = new OptionSet().Add("m|merge", delegate (string v) { options["merge"] = v != null; }); + + List mainParams = optionSet.Parse(cmdparams); + + if (mainParams.Count < 6) + { + m_log.Error( + "[INVENTORY ARCHIVER]: usage is load iar []"); + return; + } + + string firstName = mainParams[2]; + string lastName = mainParams[3]; + string invPath = mainParams[4]; + string pass = mainParams[5]; + string loadPath = (mainParams.Count > 6 ? mainParams[6] : DEFAULT_INV_BACKUP_FILENAME); + m_log.InfoFormat( - "[INVENTORY ARCHIVER]: Loaded archive {0} for {1} {2}", - loadPath, firstName, lastName); + "[INVENTORY ARCHIVER]: Loading archive {0} to inventory path {1} for {2} {3}", + loadPath, invPath, firstName, lastName); + + if (DearchiveInventory(firstName, lastName, invPath, pass, loadPath, options)) + m_log.InfoFormat( + "[INVENTORY ARCHIVER]: Loaded archive {0} for {1} {2}", + loadPath, firstName, lastName); + } + catch (InventoryArchiverException e) + { + m_log.ErrorFormat("[INVENTORY ARCHIVER]: {0}", e.Message); + } } /// @@ -358,30 +365,38 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// protected void HandleSaveInvConsoleCommand(string module, string[] cmdparams) { - if (cmdparams.Length < 6) + Guid id = Guid.NewGuid(); + + try { - m_log.Error( - "[INVENTORY ARCHIVER]: usage is save iar []"); - return; + if (cmdparams.Length < 6) + { + m_log.Error( + "[INVENTORY ARCHIVER]: usage is save iar []"); + return; + } + + m_log.Info("[INVENTORY ARCHIVER]: PLEASE NOTE THAT THIS FACILITY IS EXPERIMENTAL. BUG REPORTS WELCOME."); + + string firstName = cmdparams[2]; + string lastName = cmdparams[3]; + string invPath = cmdparams[4]; + string pass = cmdparams[5]; + string savePath = (cmdparams.Length > 6 ? cmdparams[6] : DEFAULT_INV_BACKUP_FILENAME); + + m_log.InfoFormat( + "[INVENTORY ARCHIVER]: Saving archive {0} using inventory path {1} for {2} {3}", + savePath, invPath, firstName, lastName); + + ArchiveInventory(id, firstName, lastName, invPath, pass, savePath, new Dictionary()); } - - m_log.Info("[INVENTORY ARCHIVER]: PLEASE NOTE THAT THIS FACILITY IS EXPERIMENTAL. BUG REPORTS WELCOME."); - - string firstName = cmdparams[2]; - string lastName = cmdparams[3]; - string invPath = cmdparams[4]; - string pass = cmdparams[5]; - string savePath = (cmdparams.Length > 6 ? cmdparams[6] : DEFAULT_INV_BACKUP_FILENAME); - - m_log.InfoFormat( - "[INVENTORY ARCHIVER]: Saving archive {0} using inventory path {1} for {2} {3}", - savePath, invPath, firstName, lastName); - - Guid id = Guid.NewGuid(); - ArchiveInventory(id, firstName, lastName, invPath, pass, savePath, new Dictionary()); - + catch (InventoryArchiverException e) + { + m_log.ErrorFormat("[INVENTORY ARCHIVER]: {0}", e.Message); + } + lock (m_pendingConsoleSaves) - m_pendingConsoleSaves.Add(id); + m_pendingConsoleSaves.Add(id); } private void SaveInvConsoleCommandCompleted( -- cgit v1.1