diff options
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs | 96 | ||||
-rw-r--r-- | OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs | 9 | ||||
-rw-r--r-- | OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs | 139 | ||||
-rw-r--r-- | OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverException.cs (renamed from OpenSim/Framework/ConfigBase.cs) | 16 | ||||
-rw-r--r-- | OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs | 111 | ||||
-rw-r--r-- | OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs | 125 |
6 files changed, 318 insertions, 178 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs index f130b3e..7683288 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs | |||
@@ -100,37 +100,37 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
100 | /// </returns> | 100 | /// </returns> |
101 | public HashSet<InventoryNodeBase> Execute() | 101 | public HashSet<InventoryNodeBase> Execute() |
102 | { | 102 | { |
103 | string filePath = "ERROR"; | ||
104 | int successfulAssetRestores = 0; | ||
105 | int failedAssetRestores = 0; | ||
106 | int successfulItemRestores = 0; | ||
107 | |||
108 | HashSet<InventoryNodeBase> loadedNodes = new HashSet<InventoryNodeBase>(); | ||
109 | |||
110 | List<InventoryFolderBase> folderCandidates | ||
111 | = InventoryArchiveUtils.FindFolderByPath( | ||
112 | m_scene.InventoryService, m_userInfo.PrincipalID, m_invPath); | ||
113 | |||
114 | if (folderCandidates.Count == 0) | ||
115 | { | ||
116 | // Possibly provide an option later on to automatically create this folder if it does not exist | ||
117 | m_log.ErrorFormat("[INVENTORY ARCHIVER]: Inventory path {0} does not exist", m_invPath); | ||
118 | |||
119 | return loadedNodes; | ||
120 | } | ||
121 | |||
122 | InventoryFolderBase rootDestinationFolder = folderCandidates[0]; | ||
123 | archive = new TarArchiveReader(m_loadStream); | ||
124 | |||
125 | // In order to load identically named folders, we need to keep track of the folders that we have already | ||
126 | // resolved | ||
127 | Dictionary <string, InventoryFolderBase> resolvedFolders = new Dictionary<string, InventoryFolderBase>(); | ||
128 | |||
129 | byte[] data; | ||
130 | TarArchiveReader.TarEntryType entryType; | ||
131 | |||
132 | try | 103 | try |
133 | { | 104 | { |
105 | string filePath = "ERROR"; | ||
106 | int successfulAssetRestores = 0; | ||
107 | int failedAssetRestores = 0; | ||
108 | int successfulItemRestores = 0; | ||
109 | |||
110 | HashSet<InventoryNodeBase> loadedNodes = new HashSet<InventoryNodeBase>(); | ||
111 | |||
112 | List<InventoryFolderBase> folderCandidates | ||
113 | = InventoryArchiveUtils.FindFolderByPath( | ||
114 | m_scene.InventoryService, m_userInfo.PrincipalID, m_invPath); | ||
115 | |||
116 | if (folderCandidates.Count == 0) | ||
117 | { | ||
118 | // Possibly provide an option later on to automatically create this folder if it does not exist | ||
119 | m_log.ErrorFormat("[INVENTORY ARCHIVER]: Inventory path {0} does not exist", m_invPath); | ||
120 | |||
121 | return loadedNodes; | ||
122 | } | ||
123 | |||
124 | InventoryFolderBase rootDestinationFolder = folderCandidates[0]; | ||
125 | archive = new TarArchiveReader(m_loadStream); | ||
126 | |||
127 | // In order to load identically named folders, we need to keep track of the folders that we have already | ||
128 | // resolved | ||
129 | Dictionary <string, InventoryFolderBase> resolvedFolders = new Dictionary<string, InventoryFolderBase>(); | ||
130 | |||
131 | byte[] data; | ||
132 | TarArchiveReader.TarEntryType entryType; | ||
133 | |||
134 | while ((data = archive.ReadEntry(out filePath, out entryType)) != null) | 134 | while ((data = archive.ReadEntry(out filePath, out entryType)) != null) |
135 | { | 135 | { |
136 | if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH)) | 136 | if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH)) |
@@ -173,18 +173,20 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
173 | } | 173 | } |
174 | } | 174 | } |
175 | } | 175 | } |
176 | |||
177 | archive.Close(); | ||
178 | |||
179 | m_log.DebugFormat( | ||
180 | "[INVENTORY ARCHIVER]: Successfully loaded {0} assets with {1} failures", | ||
181 | successfulAssetRestores, failedAssetRestores); | ||
182 | m_log.InfoFormat("[INVENTORY ARCHIVER]: Successfully loaded {0} items", successfulItemRestores); | ||
183 | |||
184 | return loadedNodes; | ||
176 | } | 185 | } |
177 | finally | 186 | finally |
178 | { | 187 | { |
179 | archive.Close(); | 188 | m_loadStream.Close(); |
180 | } | 189 | } |
181 | |||
182 | m_log.DebugFormat( | ||
183 | "[INVENTORY ARCHIVER]: Successfully loaded {0} assets with {1} failures", | ||
184 | successfulAssetRestores, failedAssetRestores); | ||
185 | m_log.InfoFormat("[INVENTORY ARCHIVER]: Successfully loaded {0} items", successfulItemRestores); | ||
186 | |||
187 | return loadedNodes; | ||
188 | } | 190 | } |
189 | 191 | ||
190 | public void Close() | 192 | public void Close() |
@@ -220,9 +222,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
220 | InventoryFolderBase destFolder | 222 | InventoryFolderBase destFolder |
221 | = ResolveDestinationFolder(rootDestFolder, ref iarPathExisting, resolvedFolders); | 223 | = ResolveDestinationFolder(rootDestFolder, ref iarPathExisting, resolvedFolders); |
222 | 224 | ||
223 | m_log.DebugFormat( | 225 | // m_log.DebugFormat( |
224 | "[INVENTORY ARCHIVER]: originalArchivePath [{0}], section already loaded [{1}]", | 226 | // "[INVENTORY ARCHIVER]: originalArchivePath [{0}], section already loaded [{1}]", |
225 | iarPath, iarPathExisting); | 227 | // iarPath, iarPathExisting); |
226 | 228 | ||
227 | string iarPathToCreate = iarPath.Substring(iarPathExisting.Length); | 229 | string iarPathToCreate = iarPath.Substring(iarPathExisting.Length); |
228 | CreateFoldersForPath(destFolder, iarPathExisting, iarPathToCreate, resolvedFolders, loadedNodes); | 230 | CreateFoldersForPath(destFolder, iarPathExisting, iarPathToCreate, resolvedFolders, loadedNodes); |
@@ -255,7 +257,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
255 | ref string archivePath, | 257 | ref string archivePath, |
256 | Dictionary <string, InventoryFolderBase> resolvedFolders) | 258 | Dictionary <string, InventoryFolderBase> resolvedFolders) |
257 | { | 259 | { |
258 | string originalArchivePath = archivePath; | 260 | // string originalArchivePath = archivePath; |
259 | 261 | ||
260 | while (archivePath.Length > 0) | 262 | while (archivePath.Length > 0) |
261 | { | 263 | { |
@@ -263,8 +265,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
263 | 265 | ||
264 | if (resolvedFolders.ContainsKey(archivePath)) | 266 | if (resolvedFolders.ContainsKey(archivePath)) |
265 | { | 267 | { |
266 | m_log.DebugFormat( | 268 | // m_log.DebugFormat( |
267 | "[INVENTORY ARCHIVER]: Found previously created folder from archive path {0}", archivePath); | 269 | // "[INVENTORY ARCHIVER]: Found previously created folder from archive path {0}", archivePath); |
268 | return resolvedFolders[archivePath]; | 270 | return resolvedFolders[archivePath]; |
269 | } | 271 | } |
270 | else | 272 | else |
@@ -296,9 +298,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
296 | } | 298 | } |
297 | else | 299 | else |
298 | { | 300 | { |
299 | m_log.DebugFormat( | 301 | // m_log.DebugFormat( |
300 | "[INVENTORY ARCHIVER]: Found no previously created folder for archive path {0}", | 302 | // "[INVENTORY ARCHIVER]: Found no previously created folder for archive path {0}", |
301 | originalArchivePath); | 303 | // originalArchivePath); |
302 | archivePath = string.Empty; | 304 | archivePath = string.Empty; |
303 | return rootDestFolder; | 305 | return rootDestFolder; |
304 | } | 306 | } |
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs index ca33968..84afb40 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs | |||
@@ -206,11 +206,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
206 | 206 | ||
207 | if (components.Length == 1) | 207 | if (components.Length == 1) |
208 | { | 208 | { |
209 | // m_log.DebugFormat("FOUND SINGLE COMPONENT [{0}]", components[0]); | 209 | // m_log.DebugFormat( |
210 | // "FOUND SINGLE COMPONENT [{0}]. Looking for this in [{1}] {2}", | ||
211 | // components[0], startFolder.Name, startFolder.ID); | ||
210 | 212 | ||
211 | List<InventoryItemBase> items = inventoryService.GetFolderItems(startFolder.Owner, startFolder.ID); | 213 | List<InventoryItemBase> items = inventoryService.GetFolderItems(startFolder.Owner, startFolder.ID); |
214 | |||
215 | // m_log.DebugFormat("[INVENTORY ARCHIVE UTILS]: Found {0} items in FindItemByPath()", items.Count); | ||
216 | |||
212 | foreach (InventoryItemBase item in items) | 217 | foreach (InventoryItemBase item in items) |
213 | { | 218 | { |
219 | // m_log.DebugFormat("[INVENTORY ARCHIVE UTILS]: Inspecting item {0} {1}", item.Name, item.ID); | ||
220 | |||
214 | if (item.Name == components[0]) | 221 | if (item.Name == components[0]) |
215 | return item; | 222 | return item; |
216 | } | 223 | } |
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 | |||
119 | protected void ReceivedAllAssets(ICollection<UUID> assetsFoundUuids, ICollection<UUID> assetsNotFoundUuids) | 119 | protected void ReceivedAllAssets(ICollection<UUID> assetsFoundUuids, ICollection<UUID> assetsNotFoundUuids) |
120 | { | 120 | { |
121 | Exception reportedException = null; | 121 | Exception reportedException = null; |
122 | bool succeeded = true; | 122 | bool succeeded = true; |
123 | 123 | ||
124 | try | 124 | try |
125 | { | 125 | { |
126 | // We're almost done. Just need to write out the control file now | 126 | // We're almost done. Just need to write out the control file now |
127 | m_archiveWriter.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, Create0p1ControlFile()); | 127 | m_archiveWriter.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, Create0p1ControlFile()); |
128 | m_log.InfoFormat("[ARCHIVER]: Added control file to archive."); | 128 | m_log.InfoFormat("[ARCHIVER]: Added control file to archive."); |
129 | |||
130 | m_archiveWriter.Close(); | 129 | m_archiveWriter.Close(); |
131 | } | 130 | } |
132 | catch (Exception e) | 131 | catch (Exception e) |
133 | { | 132 | { |
134 | m_saveStream.Close(); | ||
135 | reportedException = e; | 133 | reportedException = e; |
136 | succeeded = false; | 134 | succeeded = false; |
137 | } | 135 | } |
136 | finally | ||
137 | { | ||
138 | m_saveStream.Close(); | ||
139 | } | ||
138 | 140 | ||
139 | m_module.TriggerInventoryArchiveSaved( | 141 | m_module.TriggerInventoryArchiveSaved( |
140 | m_id, succeeded, m_userInfo, m_invPath, m_saveStream, reportedException); | 142 | m_id, succeeded, m_userInfo, m_invPath, m_saveStream, reportedException); |
@@ -213,70 +215,68 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
213 | /// </summary> | 215 | /// </summary> |
214 | public void Execute() | 216 | public void Execute() |
215 | { | 217 | { |
216 | InventoryFolderBase inventoryFolder = null; | 218 | try |
217 | InventoryItemBase inventoryItem = null; | ||
218 | InventoryFolderBase rootFolder = m_scene.InventoryService.GetRootFolder(m_userInfo.PrincipalID); | ||
219 | |||
220 | bool foundStar = false; | ||
221 | |||
222 | // Eliminate double slashes and any leading / on the path. | ||
223 | string[] components | ||
224 | = m_invPath.Split( | ||
225 | new string[] { InventoryFolderImpl.PATH_DELIMITER }, StringSplitOptions.RemoveEmptyEntries); | ||
226 | |||
227 | int maxComponentIndex = components.Length - 1; | ||
228 | |||
229 | // If the path terminates with a STAR then later on we want to archive all nodes in the folder but not the | ||
230 | // folder itself. This may get more sophisicated later on | ||
231 | if (maxComponentIndex >= 0 && components[maxComponentIndex] == STAR_WILDCARD) | ||
232 | { | ||
233 | foundStar = true; | ||
234 | maxComponentIndex--; | ||
235 | } | ||
236 | |||
237 | m_invPath = String.Empty; | ||
238 | for (int i = 0; i <= maxComponentIndex; i++) | ||
239 | { | ||
240 | m_invPath += components[i] + InventoryFolderImpl.PATH_DELIMITER; | ||
241 | } | ||
242 | |||
243 | // Annoyingly Split actually returns the original string if the input string consists only of delimiters | ||
244 | // Therefore if we still start with a / after the split, then we need the root folder | ||
245 | if (m_invPath.Length == 0) | ||
246 | { | ||
247 | inventoryFolder = rootFolder; | ||
248 | } | ||
249 | else | ||
250 | { | ||
251 | m_invPath = m_invPath.Remove(m_invPath.LastIndexOf(InventoryFolderImpl.PATH_DELIMITER)); | ||
252 | List<InventoryFolderBase> candidateFolders | ||
253 | = InventoryArchiveUtils.FindFolderByPath(m_scene.InventoryService, rootFolder, m_invPath); | ||
254 | if (candidateFolders.Count > 0) | ||
255 | inventoryFolder = candidateFolders[0]; | ||
256 | } | ||
257 | |||
258 | // The path may point to an item instead | ||
259 | if (inventoryFolder == null) | ||
260 | { | ||
261 | inventoryItem = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, rootFolder, m_invPath); | ||
262 | //inventoryItem = m_userInfo.RootFolder.FindItemByPath(m_invPath); | ||
263 | } | ||
264 | |||
265 | if (null == inventoryFolder && null == inventoryItem) | ||
266 | { | 219 | { |
267 | // We couldn't find the path indicated | 220 | InventoryFolderBase inventoryFolder = null; |
268 | string errorMessage = string.Format("Aborted save. Could not find inventory path {0}", m_invPath); | 221 | InventoryItemBase inventoryItem = null; |
269 | m_log.ErrorFormat("[INVENTORY ARCHIVER]: {0}", errorMessage); | 222 | InventoryFolderBase rootFolder = m_scene.InventoryService.GetRootFolder(m_userInfo.PrincipalID); |
270 | m_module.TriggerInventoryArchiveSaved( | 223 | |
271 | m_id, false, m_userInfo, m_invPath, m_saveStream, | 224 | bool foundStar = false; |
272 | new Exception(errorMessage)); | 225 | |
273 | return; | 226 | // Eliminate double slashes and any leading / on the path. |
274 | } | 227 | string[] components |
228 | = m_invPath.Split( | ||
229 | new string[] { InventoryFolderImpl.PATH_DELIMITER }, StringSplitOptions.RemoveEmptyEntries); | ||
230 | |||
231 | int maxComponentIndex = components.Length - 1; | ||
232 | |||
233 | // If the path terminates with a STAR then later on we want to archive all nodes in the folder but not the | ||
234 | // folder itself. This may get more sophisicated later on | ||
235 | if (maxComponentIndex >= 0 && components[maxComponentIndex] == STAR_WILDCARD) | ||
236 | { | ||
237 | foundStar = true; | ||
238 | maxComponentIndex--; | ||
239 | } | ||
240 | |||
241 | m_invPath = String.Empty; | ||
242 | for (int i = 0; i <= maxComponentIndex; i++) | ||
243 | { | ||
244 | m_invPath += components[i] + InventoryFolderImpl.PATH_DELIMITER; | ||
245 | } | ||
246 | |||
247 | // Annoyingly Split actually returns the original string if the input string consists only of delimiters | ||
248 | // Therefore if we still start with a / after the split, then we need the root folder | ||
249 | if (m_invPath.Length == 0) | ||
250 | { | ||
251 | inventoryFolder = rootFolder; | ||
252 | } | ||
253 | else | ||
254 | { | ||
255 | m_invPath = m_invPath.Remove(m_invPath.LastIndexOf(InventoryFolderImpl.PATH_DELIMITER)); | ||
256 | List<InventoryFolderBase> candidateFolders | ||
257 | = InventoryArchiveUtils.FindFolderByPath(m_scene.InventoryService, rootFolder, m_invPath); | ||
258 | if (candidateFolders.Count > 0) | ||
259 | inventoryFolder = candidateFolders[0]; | ||
260 | } | ||
261 | |||
262 | // The path may point to an item instead | ||
263 | if (inventoryFolder == null) | ||
264 | { | ||
265 | inventoryItem = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, rootFolder, m_invPath); | ||
266 | //inventoryItem = m_userInfo.RootFolder.FindItemByPath(m_invPath); | ||
267 | } | ||
268 | |||
269 | if (null == inventoryFolder && null == inventoryItem) | ||
270 | { | ||
271 | // We couldn't find the path indicated | ||
272 | string errorMessage = string.Format("Aborted save. Could not find inventory path {0}", m_invPath); | ||
273 | Exception e = new InventoryArchiverException(errorMessage); | ||
274 | m_module.TriggerInventoryArchiveSaved(m_id, false, m_userInfo, m_invPath, m_saveStream, e); | ||
275 | throw e; | ||
276 | } | ||
275 | 277 | ||
276 | m_archiveWriter = new TarArchiveWriter(m_saveStream); | 278 | m_archiveWriter = new TarArchiveWriter(m_saveStream); |
277 | 279 | ||
278 | try | ||
279 | { | ||
280 | if (inventoryFolder != null) | 280 | if (inventoryFolder != null) |
281 | { | 281 | { |
282 | m_log.DebugFormat( | 282 | m_log.DebugFormat( |
@@ -297,16 +297,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
297 | 297 | ||
298 | // Don't put all this profile information into the archive right now. | 298 | // Don't put all this profile information into the archive right now. |
299 | //SaveUsers(); | 299 | //SaveUsers(); |
300 | |||
301 | new AssetsRequest( | ||
302 | new AssetsArchiver(m_archiveWriter), m_assetUuids, m_scene.AssetService, ReceivedAllAssets).Execute(); | ||
300 | } | 303 | } |
301 | catch (Exception) | 304 | catch (Exception) |
302 | { | 305 | { |
303 | m_archiveWriter.Close(); | 306 | m_saveStream.Close(); |
304 | throw; | 307 | throw; |
305 | } | 308 | } |
306 | |||
307 | new AssetsRequest( | ||
308 | new AssetsArchiver(m_archiveWriter), m_assetUuids, | ||
309 | m_scene.AssetService, ReceivedAllAssets).Execute(); | ||
310 | } | 309 | } |
311 | 310 | ||
312 | /// <summary> | 311 | /// <summary> |
diff --git a/OpenSim/Framework/ConfigBase.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverException.cs index 40ec32f..e07e2ca 100644 --- a/OpenSim/Framework/ConfigBase.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverException.cs | |||
@@ -26,13 +26,15 @@ | |||
26 | */ | 26 | */ |
27 | 27 | ||
28 | using System; | 28 | using System; |
29 | using System.Collections.Generic; | ||
30 | using System.Text; | ||
31 | 29 | ||
32 | namespace OpenSim.Framework | 30 | namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver |
33 | { | 31 | { |
34 | public abstract class ConfigBase | 32 | /// <summary> |
35 | { | 33 | /// Signals an inventory archiving problem |
36 | protected ConfigurationMember m_configMember; | 34 | /// </summary> |
35 | public class InventoryArchiverException : Exception | ||
36 | { | ||
37 | public InventoryArchiverException(string message) : base(message) {} | ||
38 | public InventoryArchiverException(string message, Exception e) : base(message, e) {} | ||
37 | } | 39 | } |
38 | } | 40 | } \ 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 668c344..f03f2a1 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs | |||
@@ -324,34 +324,41 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
324 | /// <param name="cmdparams"></param> | 324 | /// <param name="cmdparams"></param> |
325 | protected void HandleLoadInvConsoleCommand(string module, string[] cmdparams) | 325 | protected void HandleLoadInvConsoleCommand(string module, string[] cmdparams) |
326 | { | 326 | { |
327 | m_log.Info("[INVENTORY ARCHIVER]: PLEASE NOTE THAT THIS FACILITY IS EXPERIMENTAL. BUG REPORTS WELCOME."); | 327 | try |
328 | 328 | { | |
329 | Dictionary<string, object> options = new Dictionary<string, object>(); | 329 | m_log.Info("[INVENTORY ARCHIVER]: PLEASE NOTE THAT THIS FACILITY IS EXPERIMENTAL. BUG REPORTS WELCOME."); |
330 | OptionSet optionSet = new OptionSet().Add("m|merge", delegate (string v) { options["merge"] = v != null; }); | 330 | |
331 | 331 | Dictionary<string, object> options = new Dictionary<string, object>(); | |
332 | List<string> mainParams = optionSet.Parse(cmdparams); | 332 | OptionSet optionSet = new OptionSet().Add("m|merge", delegate (string v) { options["merge"] = v != null; }); |
333 | 333 | ||
334 | if (mainParams.Count < 6) | 334 | List<string> mainParams = optionSet.Parse(cmdparams); |
335 | { | 335 | |
336 | m_log.Error( | 336 | if (mainParams.Count < 6) |
337 | "[INVENTORY ARCHIVER]: usage is load iar <first name> <last name> <inventory path> <user password> [<load file path>]"); | 337 | { |
338 | return; | 338 | m_log.Error( |
339 | } | 339 | "[INVENTORY ARCHIVER]: usage is load iar [--merge] <first name> <last name> <inventory path> <user password> [<load file path>]"); |
340 | 340 | return; | |
341 | string firstName = mainParams[2]; | 341 | } |
342 | string lastName = mainParams[3]; | 342 | |
343 | string invPath = mainParams[4]; | 343 | string firstName = mainParams[2]; |
344 | string pass = mainParams[5]; | 344 | string lastName = mainParams[3]; |
345 | string loadPath = (mainParams.Count > 6 ? mainParams[6] : DEFAULT_INV_BACKUP_FILENAME); | 345 | string invPath = mainParams[4]; |
346 | 346 | string pass = mainParams[5]; | |
347 | m_log.InfoFormat( | 347 | string loadPath = (mainParams.Count > 6 ? mainParams[6] : DEFAULT_INV_BACKUP_FILENAME); |
348 | "[INVENTORY ARCHIVER]: Loading archive {0} to inventory path {1} for {2} {3}", | 348 | |
349 | loadPath, invPath, firstName, lastName); | ||
350 | |||
351 | if (DearchiveInventory(firstName, lastName, invPath, pass, loadPath, options)) | ||
352 | m_log.InfoFormat( | 349 | m_log.InfoFormat( |
353 | "[INVENTORY ARCHIVER]: Loaded archive {0} for {1} {2}", | 350 | "[INVENTORY ARCHIVER]: Loading archive {0} to inventory path {1} for {2} {3}", |
354 | loadPath, firstName, lastName); | 351 | loadPath, invPath, firstName, lastName); |
352 | |||
353 | if (DearchiveInventory(firstName, lastName, invPath, pass, loadPath, options)) | ||
354 | m_log.InfoFormat( | ||
355 | "[INVENTORY ARCHIVER]: Loaded archive {0} for {1} {2}", | ||
356 | loadPath, firstName, lastName); | ||
357 | } | ||
358 | catch (InventoryArchiverException e) | ||
359 | { | ||
360 | m_log.ErrorFormat("[INVENTORY ARCHIVER]: {0}", e.Message); | ||
361 | } | ||
355 | } | 362 | } |
356 | 363 | ||
357 | /// <summary> | 364 | /// <summary> |
@@ -360,30 +367,38 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver | |||
360 | /// <param name="cmdparams"></param> | 367 | /// <param name="cmdparams"></param> |
361 | protected void HandleSaveInvConsoleCommand(string module, string[] cmdparams) | 368 | protected void HandleSaveInvConsoleCommand(string module, string[] cmdparams) |
362 | { | 369 | { |
363 | if (cmdparams.Length < 6) | 370 | Guid id = Guid.NewGuid(); |
371 | |||
372 | try | ||
364 | { | 373 | { |
365 | m_log.Error( | 374 | if (cmdparams.Length < 6) |
366 | "[INVENTORY ARCHIVER]: usage is save iar <first name> <last name> <inventory path> <user password> [<save file path>]"); | 375 | { |
367 | return; | 376 | m_log.Error( |
377 | "[INVENTORY ARCHIVER]: usage is save iar <first name> <last name> <inventory path> <user password> [<save file path>]"); | ||
378 | return; | ||
379 | } | ||
380 | |||
381 | m_log.Info("[INVENTORY ARCHIVER]: PLEASE NOTE THAT THIS FACILITY IS EXPERIMENTAL. BUG REPORTS WELCOME."); | ||
382 | |||
383 | string firstName = cmdparams[2]; | ||
384 | string lastName = cmdparams[3]; | ||
385 | string invPath = cmdparams[4]; | ||
386 | string pass = cmdparams[5]; | ||
387 | string savePath = (cmdparams.Length > 6 ? cmdparams[6] : DEFAULT_INV_BACKUP_FILENAME); | ||
388 | |||
389 | m_log.InfoFormat( | ||
390 | "[INVENTORY ARCHIVER]: Saving archive {0} using inventory path {1} for {2} {3}", | ||
391 | savePath, invPath, firstName, lastName); | ||
392 | |||
393 | ArchiveInventory(id, firstName, lastName, invPath, pass, savePath, new Dictionary<string, object>()); | ||
368 | } | 394 | } |
369 | 395 | catch (InventoryArchiverException e) | |
370 | m_log.Info("[INVENTORY ARCHIVER]: PLEASE NOTE THAT THIS FACILITY IS EXPERIMENTAL. BUG REPORTS WELCOME."); | 396 | { |
371 | 397 | m_log.ErrorFormat("[INVENTORY ARCHIVER]: {0}", e.Message); | |
372 | string firstName = cmdparams[2]; | 398 | } |
373 | string lastName = cmdparams[3]; | 399 | |
374 | string invPath = cmdparams[4]; | ||
375 | string pass = cmdparams[5]; | ||
376 | string savePath = (cmdparams.Length > 6 ? cmdparams[6] : DEFAULT_INV_BACKUP_FILENAME); | ||
377 | |||
378 | m_log.InfoFormat( | ||
379 | "[INVENTORY ARCHIVER]: Saving archive {0} using inventory path {1} for {2} {3}", | ||
380 | savePath, invPath, firstName, lastName); | ||
381 | |||
382 | Guid id = Guid.NewGuid(); | ||
383 | ArchiveInventory(id, firstName, lastName, invPath, pass, savePath, new Dictionary<string, object>()); | ||
384 | |||
385 | lock (m_pendingConsoleSaves) | 400 | lock (m_pendingConsoleSaves) |
386 | m_pendingConsoleSaves.Add(id); | 401 | m_pendingConsoleSaves.Add(id); |
387 | } | 402 | } |
388 | 403 | ||
389 | private void SaveInvConsoleCommandCompleted( | 404 | 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 5fad0a9..2d80382 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs | |||
@@ -63,13 +63,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests | |||
63 | } | 63 | } |
64 | 64 | ||
65 | /// <summary> | 65 | /// <summary> |
66 | /// Test saving a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet). | 66 | /// Test saving an inventory path to a V0.1 OpenSim Inventory Archive |
67 | /// (subject to change since there is no fixed format yet). | ||
67 | /// </summary> | 68 | /// </summary> |
68 | // Commenting for now! The mock inventory service needs more beef, at least for | ||
69 | // GetFolderForType | ||
70 | // REFACTORING PROBLEM. This needs to be rewritten. | ||
71 | [Test] | 69 | [Test] |
72 | public void TestSaveIarV0_1() | 70 | public void TestSavePathToIarV0_1() |
73 | { | 71 | { |
74 | TestHelper.InMethod(); | 72 | TestHelper.InMethod(); |
75 | // log4net.Config.XmlConfigurator.Configure(); | 73 | // log4net.Config.XmlConfigurator.Configure(); |
@@ -182,6 +180,123 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests | |||
182 | } | 180 | } |
183 | 181 | ||
184 | /// <summary> | 182 | /// <summary> |
183 | /// Test saving a single inventory item to a V0.1 OpenSim Inventory Archive | ||
184 | /// (subject to change since there is no fixed format yet). | ||
185 | /// </summary> | ||
186 | [Test] | ||
187 | public void TestSaveItemToIarV0_1() | ||
188 | { | ||
189 | TestHelper.InMethod(); | ||
190 | // log4net.Config.XmlConfigurator.Configure(); | ||
191 | |||
192 | InventoryArchiverModule archiverModule = new InventoryArchiverModule(true); | ||
193 | |||
194 | Scene scene = SceneSetupHelpers.SetupScene("Inventory"); | ||
195 | SceneSetupHelpers.SetupSceneModules(scene, archiverModule); | ||
196 | |||
197 | // Create user | ||
198 | string userFirstName = "Jock"; | ||
199 | string userLastName = "Stirrup"; | ||
200 | string userPassword = "troll"; | ||
201 | UUID userId = UUID.Parse("00000000-0000-0000-0000-000000000020"); | ||
202 | UserProfileTestUtils.CreateUserWithInventory(scene, userFirstName, userLastName, userId, userPassword); | ||
203 | |||
204 | // Create asset | ||
205 | SceneObjectGroup object1; | ||
206 | SceneObjectPart part1; | ||
207 | { | ||
208 | string partName = "My Little Dog Object"; | ||
209 | UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000040"); | ||
210 | PrimitiveBaseShape shape = PrimitiveBaseShape.CreateSphere(); | ||
211 | Vector3 groupPosition = new Vector3(10, 20, 30); | ||
212 | Quaternion rotationOffset = new Quaternion(20, 30, 40, 50); | ||
213 | Vector3 offsetPosition = new Vector3(5, 10, 15); | ||
214 | |||
215 | part1 | ||
216 | = new SceneObjectPart( | ||
217 | ownerId, shape, groupPosition, rotationOffset, offsetPosition); | ||
218 | part1.Name = partName; | ||
219 | |||
220 | object1 = new SceneObjectGroup(part1); | ||
221 | scene.AddNewSceneObject(object1, false); | ||
222 | } | ||
223 | |||
224 | UUID asset1Id = UUID.Parse("00000000-0000-0000-0000-000000000060"); | ||
225 | AssetBase asset1 = AssetHelpers.CreateAsset(asset1Id, object1); | ||
226 | scene.AssetService.Store(asset1); | ||
227 | |||
228 | // Create item | ||
229 | UUID item1Id = UUID.Parse("00000000-0000-0000-0000-000000000080"); | ||
230 | string item1Name = "My Little Dog"; | ||
231 | InventoryItemBase item1 = new InventoryItemBase(); | ||
232 | item1.Name = item1Name; | ||
233 | item1.AssetID = asset1.FullID; | ||
234 | item1.ID = item1Id; | ||
235 | InventoryFolderBase objsFolder | ||
236 | = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, userId, "Objects")[0]; | ||
237 | item1.Folder = objsFolder.ID; | ||
238 | scene.AddInventoryItem(userId, item1); | ||
239 | |||
240 | MemoryStream archiveWriteStream = new MemoryStream(); | ||
241 | archiverModule.OnInventoryArchiveSaved += SaveCompleted; | ||
242 | |||
243 | mre.Reset(); | ||
244 | archiverModule.ArchiveInventory( | ||
245 | Guid.NewGuid(), userFirstName, userLastName, "Objects/" + item1Name, userPassword, archiveWriteStream); | ||
246 | mre.WaitOne(60000, false); | ||
247 | |||
248 | byte[] archive = archiveWriteStream.ToArray(); | ||
249 | MemoryStream archiveReadStream = new MemoryStream(archive); | ||
250 | TarArchiveReader tar = new TarArchiveReader(archiveReadStream); | ||
251 | |||
252 | //bool gotControlFile = false; | ||
253 | bool gotObject1File = false; | ||
254 | //bool gotObject2File = false; | ||
255 | string expectedObject1FileName = InventoryArchiveWriteRequest.CreateArchiveItemName(item1); | ||
256 | string expectedObject1FilePath = string.Format( | ||
257 | "{0}{1}", | ||
258 | ArchiveConstants.INVENTORY_PATH, | ||
259 | expectedObject1FileName); | ||
260 | |||
261 | string filePath; | ||
262 | TarArchiveReader.TarEntryType tarEntryType; | ||
263 | |||
264 | // Console.WriteLine("Reading archive"); | ||
265 | |||
266 | while (tar.ReadEntry(out filePath, out tarEntryType) != null) | ||
267 | { | ||
268 | Console.WriteLine("Got {0}", filePath); | ||
269 | |||
270 | // if (ArchiveConstants.CONTROL_FILE_PATH == filePath) | ||
271 | // { | ||
272 | // gotControlFile = true; | ||
273 | // } | ||
274 | |||
275 | if (filePath.StartsWith(ArchiveConstants.INVENTORY_PATH) && filePath.EndsWith(".xml")) | ||
276 | { | ||
277 | // string fileName = filePath.Remove(0, "Objects/".Length); | ||
278 | // | ||
279 | // if (fileName.StartsWith(part1.Name)) | ||
280 | // { | ||
281 | Assert.That(expectedObject1FilePath, Is.EqualTo(filePath)); | ||
282 | gotObject1File = true; | ||
283 | // } | ||
284 | // else if (fileName.StartsWith(part2.Name)) | ||
285 | // { | ||
286 | // Assert.That(fileName, Is.EqualTo(expectedObject2FileName)); | ||
287 | // gotObject2File = true; | ||
288 | // } | ||
289 | } | ||
290 | } | ||
291 | |||
292 | // Assert.That(gotControlFile, Is.True, "No control file in archive"); | ||
293 | Assert.That(gotObject1File, Is.True, "No item1 file in archive"); | ||
294 | // Assert.That(gotObject2File, Is.True, "No object2 file in archive"); | ||
295 | |||
296 | // TODO: Test presence of more files and contents of files. | ||
297 | } | ||
298 | |||
299 | /// <summary> | ||
185 | /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where | 300 | /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where |
186 | /// an account exists with the creator name. | 301 | /// an account exists with the creator name. |
187 | /// </summary> | 302 | /// </summary> |