aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs')
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs215
1 files changed, 160 insertions, 55 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
index 6030706..9b98de3 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
@@ -41,6 +41,7 @@ using OpenSim.Framework.Serialization;
41using OpenSim.Framework.Serialization.External; 41using OpenSim.Framework.Serialization.External;
42using OpenSim.Region.CoreModules.World.Archiver; 42using OpenSim.Region.CoreModules.World.Archiver;
43using OpenSim.Region.Framework.Scenes; 43using OpenSim.Region.Framework.Scenes;
44using OpenSim.Region.Framework.Scenes.Serialization;
44using OpenSim.Region.Framework.Interfaces; 45using OpenSim.Region.Framework.Interfaces;
45using OpenSim.Services.Interfaces; 46using OpenSim.Services.Interfaces;
46 47
@@ -75,6 +76,36 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
75 /// The stream from which the inventory archive will be loaded. 76 /// The stream from which the inventory archive will be loaded.
76 /// </value> 77 /// </value>
77 private Stream m_loadStream; 78 private Stream m_loadStream;
79
80 protected bool m_controlFileLoaded;
81 protected bool m_assetsLoaded;
82 protected bool m_inventoryNodesLoaded;
83
84 protected int m_successfulAssetRestores;
85 protected int m_failedAssetRestores;
86 protected int m_successfulItemRestores;
87
88 /// <summary>
89 /// Root destination folder for the IAR load.
90 /// </summary>
91 protected InventoryFolderBase m_rootDestinationFolder;
92
93 /// <summary>
94 /// Inventory nodes loaded from the iar.
95 /// </summary>
96 protected HashSet<InventoryNodeBase> m_loadedNodes = new HashSet<InventoryNodeBase>();
97
98 /// <summary>
99 /// In order to load identically named folders, we need to keep track of the folders that we have already
100 /// resolved.
101 /// </summary>
102 Dictionary <string, InventoryFolderBase> m_resolvedFolders = new Dictionary<string, InventoryFolderBase>();
103
104 /// <summary>
105 /// Record the creator id that should be associated with an asset. This is used to adjust asset creator ids
106 /// after OSP resolution (since OSP creators are only stored in the item
107 /// </summary>
108 protected Dictionary<UUID, UUID> m_creatorIdForAssetId = new Dictionary<UUID, UUID>();
78 109
79 public InventoryArchiveReadRequest( 110 public InventoryArchiveReadRequest(
80 Scene scene, UserAccount userInfo, string invPath, string loadPath, bool merge) 111 Scene scene, UserAccount userInfo, string invPath, string loadPath, bool merge)
@@ -100,20 +131,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
100 /// <summary> 131 /// <summary>
101 /// Execute the request 132 /// Execute the request
102 /// </summary> 133 /// </summary>
134 /// <remarks>
135 /// Only call this once. To load another IAR, construct another request object.
136 /// </remarks>
103 /// <returns> 137 /// <returns>
104 /// A list of the inventory nodes loaded. If folders were loaded then only the root folders are 138 /// A list of the inventory nodes loaded. If folders were loaded then only the root folders are
105 /// returned 139 /// returned
106 /// </returns> 140 /// </returns>
141 /// <exception cref="System.Exception">Thrown if load fails.</exception>
107 public HashSet<InventoryNodeBase> Execute() 142 public HashSet<InventoryNodeBase> Execute()
108 { 143 {
109 try 144 try
110 { 145 {
111 string filePath = "ERROR"; 146 string filePath = "ERROR";
112 int successfulAssetRestores = 0;
113 int failedAssetRestores = 0;
114 int successfulItemRestores = 0;
115
116 HashSet<InventoryNodeBase> loadedNodes = new HashSet<InventoryNodeBase>();
117 147
118 List<InventoryFolderBase> folderCandidates 148 List<InventoryFolderBase> folderCandidates
119 = InventoryArchiveUtils.FindFolderByPath( 149 = InventoryArchiveUtils.FindFolderByPath(
@@ -124,16 +154,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
124 // Possibly provide an option later on to automatically create this folder if it does not exist 154 // Possibly provide an option later on to automatically create this folder if it does not exist
125 m_log.ErrorFormat("[INVENTORY ARCHIVER]: Inventory path {0} does not exist", m_invPath); 155 m_log.ErrorFormat("[INVENTORY ARCHIVER]: Inventory path {0} does not exist", m_invPath);
126 156
127 return loadedNodes; 157 return m_loadedNodes;
128 } 158 }
129 159
130 InventoryFolderBase rootDestinationFolder = folderCandidates[0]; 160 m_rootDestinationFolder = folderCandidates[0];
131 archive = new TarArchiveReader(m_loadStream); 161 archive = new TarArchiveReader(m_loadStream);
132
133 // In order to load identically named folders, we need to keep track of the folders that we have already
134 // resolved
135 Dictionary <string, InventoryFolderBase> resolvedFolders = new Dictionary<string, InventoryFolderBase>();
136
137 byte[] data; 162 byte[] data;
138 TarArchiveReader.TarEntryType entryType; 163 TarArchiveReader.TarEntryType entryType;
139 164
@@ -142,45 +167,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
142 if (filePath == ArchiveConstants.CONTROL_FILE_PATH) 167 if (filePath == ArchiveConstants.CONTROL_FILE_PATH)
143 { 168 {
144 LoadControlFile(filePath, data); 169 LoadControlFile(filePath, data);
145 } 170 }
146 else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH)) 171 else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH))
147 { 172 {
148 if (LoadAsset(filePath, data)) 173 LoadAssetFile(filePath, data);
149 successfulAssetRestores++;
150 else
151 failedAssetRestores++;
152
153 if ((successfulAssetRestores) % 50 == 0)
154 m_log.DebugFormat(
155 "[INVENTORY ARCHIVER]: Loaded {0} assets...",
156 successfulAssetRestores);
157 } 174 }
158 else if (filePath.StartsWith(ArchiveConstants.INVENTORY_PATH)) 175 else if (filePath.StartsWith(ArchiveConstants.INVENTORY_PATH))
159 { 176 {
160 filePath = filePath.Substring(ArchiveConstants.INVENTORY_PATH.Length); 177 LoadInventoryFile(filePath, entryType, data);
161
162 // Trim off the file portion if we aren't already dealing with a directory path
163 if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY != entryType)
164 filePath = filePath.Remove(filePath.LastIndexOf("/") + 1);
165
166 InventoryFolderBase foundFolder
167 = ReplicateArchivePathToUserInventory(
168 filePath, rootDestinationFolder, resolvedFolders, loadedNodes);
169
170 if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY != entryType)
171 {
172 InventoryItemBase item = LoadItem(data, foundFolder);
173
174 if (item != null)
175 {
176 successfulItemRestores++;
177
178 // If we aren't loading the folder containing the item then well need to update the
179 // viewer separately for that item.
180 if (!loadedNodes.Contains(foundFolder))
181 loadedNodes.Add(item);
182 }
183 }
184 } 178 }
185 } 179 }
186 180
@@ -188,10 +182,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
188 182
189 m_log.DebugFormat( 183 m_log.DebugFormat(
190 "[INVENTORY ARCHIVER]: Successfully loaded {0} assets with {1} failures", 184 "[INVENTORY ARCHIVER]: Successfully loaded {0} assets with {1} failures",
191 successfulAssetRestores, failedAssetRestores); 185 m_successfulAssetRestores, m_failedAssetRestores);
192 m_log.InfoFormat("[INVENTORY ARCHIVER]: Successfully loaded {0} items", successfulItemRestores); 186 m_log.InfoFormat("[INVENTORY ARCHIVER]: Successfully loaded {0} items", m_successfulItemRestores);
193 187
194 return loadedNodes; 188 return m_loadedNodes;
195 } 189 }
196 finally 190 finally
197 { 191 {
@@ -400,9 +394,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
400 UUID ospResolvedId = OspResolver.ResolveOspa(item.CreatorId, m_scene.UserAccountService); 394 UUID ospResolvedId = OspResolver.ResolveOspa(item.CreatorId, m_scene.UserAccountService);
401 if (UUID.Zero != ospResolvedId) // The user exists in this grid 395 if (UUID.Zero != ospResolvedId) // The user exists in this grid
402 { 396 {
397// m_log.DebugFormat("[INVENTORY ARCHIVER]: Found creator {0} via OSPA resolution", ospResolvedId);
398
403 item.CreatorIdAsUuid = ospResolvedId; 399 item.CreatorIdAsUuid = ospResolvedId;
404 400
405 // XXX: For now, don't preserve the OSPA in the creator id (which actually gets persisted to the 401 // Don't preserve the OSPA in the creator id (which actually gets persisted to the
406 // database). Instead, replace with the UUID that we found. 402 // database). Instead, replace with the UUID that we found.
407 item.CreatorId = ospResolvedId.ToString(); 403 item.CreatorId = ospResolvedId.ToString();
408 404
@@ -410,7 +406,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
410 } 406 }
411 else if (item.CreatorData == null || item.CreatorData == String.Empty) 407 else if (item.CreatorData == null || item.CreatorData == String.Empty)
412 { 408 {
413 item.CreatorIdAsUuid = m_userInfo.PrincipalID; 409 item.CreatorId = m_userInfo.PrincipalID.ToString();
410 item.CreatorIdAsUuid = new UUID(item.CreatorId);
414 } 411 }
415 412
416 item.Owner = m_userInfo.PrincipalID; 413 item.Owner = m_userInfo.PrincipalID;
@@ -418,6 +415,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
418 // Reset folder ID to the one in which we want to load it 415 // Reset folder ID to the one in which we want to load it
419 item.Folder = loadFolder.ID; 416 item.Folder = loadFolder.ID;
420 417
418 // Record the creator id for the item's asset so that we can use it later, if necessary, when the asset
419 // is loaded.
420 // FIXME: This relies on the items coming before the assets in the TAR file. Need to create stronger
421 // checks for this, and maybe even an external tool for creating OARs which enforces this, rather than
422 // relying on native tar tools.
423 m_creatorIdForAssetId[item.AssetID] = item.CreatorIdAsUuid;
424
421 m_scene.AddInventoryItem(item); 425 m_scene.AddInventoryItem(item);
422 426
423 return item; 427 return item;
@@ -446,18 +450,38 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
446 } 450 }
447 451
448 string extension = filename.Substring(i); 452 string extension = filename.Substring(i);
449 string uuid = filename.Remove(filename.Length - extension.Length); 453 string rawUuid = filename.Remove(filename.Length - extension.Length);
454 UUID assetId = new UUID(rawUuid);
450 455
451 if (ArchiveConstants.EXTENSION_TO_ASSET_TYPE.ContainsKey(extension)) 456 if (ArchiveConstants.EXTENSION_TO_ASSET_TYPE.ContainsKey(extension))
452 { 457 {
453 sbyte assetType = ArchiveConstants.EXTENSION_TO_ASSET_TYPE[extension]; 458 sbyte assetType = ArchiveConstants.EXTENSION_TO_ASSET_TYPE[extension];
454 459
455 if (assetType == (sbyte)AssetType.Unknown) 460 if (assetType == (sbyte)AssetType.Unknown)
456 m_log.WarnFormat("[INVENTORY ARCHIVER]: Importing {0} byte asset {1} with unknown type", data.Length, uuid); 461 {
462 m_log.WarnFormat("[INVENTORY ARCHIVER]: Importing {0} byte asset {1} with unknown type", data.Length, assetId);
463 }
464 else if (assetType == (sbyte)AssetType.Object)
465 {
466 if (m_creatorIdForAssetId.ContainsKey(assetId))
467 {
468 string xmlData = Utils.BytesToString(data);
469 SceneObjectGroup sog = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
470 foreach (SceneObjectPart sop in sog.Parts)
471 {
472 if (sop.CreatorData == null || sop.CreatorData == "")
473 {
474 sop.CreatorID = m_creatorIdForAssetId[assetId];
475 }
476 }
477
478 data = Utils.StringToBytes(SceneObjectSerializer.ToOriginalXmlFormat(sog));
479 }
480 }
457 481
458 //m_log.DebugFormat("[INVENTORY ARCHIVER]: Importing asset {0}, type {1}", uuid, assetType); 482 //m_log.DebugFormat("[INVENTORY ARCHIVER]: Importing asset {0}, type {1}", uuid, assetType);
459 483
460 AssetBase asset = new AssetBase(new UUID(uuid), "RandomName", assetType, UUID.Zero.ToString()); 484 AssetBase asset = new AssetBase(assetId, "From IAR", assetType, UUID.Zero.ToString());
461 asset.Data = data; 485 asset.Data = data;
462 486
463 m_scene.AssetService.Store(asset); 487 m_scene.AssetService.Store(asset);
@@ -495,7 +519,88 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
495 majorVersion, MAX_MAJOR_VERSION)); 519 majorVersion, MAX_MAJOR_VERSION));
496 } 520 }
497 521
498 m_log.InfoFormat("[INVENTORY ARCHIVER]: Loading IAR with version {0}", version); 522 m_controlFileLoaded = true;
523 m_log.InfoFormat("[INVENTORY ARCHIVER]: Loading IAR with version {0}", version);
499 } 524 }
525
526 /// <summary>
527 /// Load inventory file
528 /// </summary>
529 /// <param name="path"></param>
530 /// <param name="entryType"></param>
531 /// <param name="data"></param>
532 protected void LoadInventoryFile(string path, TarArchiveReader.TarEntryType entryType, byte[] data)
533 {
534 if (!m_controlFileLoaded)
535 throw new Exception(
536 string.Format(
537 "The IAR you are trying to load does not list {0} before {1}. Aborting load",
538 ArchiveConstants.CONTROL_FILE_PATH, ArchiveConstants.INVENTORY_PATH));
539
540 if (m_assetsLoaded)
541 throw new Exception(
542 string.Format(
543 "The IAR you are trying to load does not list all {0} before {1}. Aborting load",
544 ArchiveConstants.INVENTORY_PATH, ArchiveConstants.ASSETS_PATH));
545
546 path = path.Substring(ArchiveConstants.INVENTORY_PATH.Length);
547
548 // Trim off the file portion if we aren't already dealing with a directory path
549 if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY != entryType)
550 path = path.Remove(path.LastIndexOf("/") + 1);
551
552 InventoryFolderBase foundFolder
553 = ReplicateArchivePathToUserInventory(
554 path, m_rootDestinationFolder, m_resolvedFolders, m_loadedNodes);
555
556 if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY != entryType)
557 {
558 InventoryItemBase item = LoadItem(data, foundFolder);
559
560 if (item != null)
561 {
562 m_successfulItemRestores++;
563
564 // If we aren't loading the folder containing the item then well need to update the
565 // viewer separately for that item.
566 if (!m_loadedNodes.Contains(foundFolder))
567 m_loadedNodes.Add(item);
568 }
569 }
570
571 m_inventoryNodesLoaded = true;
572 }
573
574 /// <summary>
575 /// Load asset file
576 /// </summary>
577 /// <param name="path"></param>
578 /// <param name="data"></param>
579 protected void LoadAssetFile(string path, byte[] data)
580 {
581 if (!m_controlFileLoaded)
582 throw new Exception(
583 string.Format(
584 "The IAR you are trying to load does not list {0} before {1}. Aborting load",
585 ArchiveConstants.CONTROL_FILE_PATH, ArchiveConstants.ASSETS_PATH));
586
587 if (!m_inventoryNodesLoaded)
588 throw new Exception(
589 string.Format(
590 "The IAR you are trying to load does not list all {0} before {1}. Aborting load",
591 ArchiveConstants.INVENTORY_PATH, ArchiveConstants.ASSETS_PATH));
592
593 if (LoadAsset(path, data))
594 m_successfulAssetRestores++;
595 else
596 m_failedAssetRestores++;
597
598 if ((m_successfulAssetRestores) % 50 == 0)
599 m_log.DebugFormat(
600 "[INVENTORY ARCHIVER]: Loaded {0} assets...",
601 m_successfulAssetRestores);
602
603 m_assetsLoaded = true;
604 }
500 } 605 }
501} \ No newline at end of file 606} \ No newline at end of file