diff options
4 files changed, 145 insertions, 27 deletions
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs index 3218abc..0cc1f86 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs | |||
@@ -51,26 +51,33 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
51 | 51 | ||
52 | private static System.Text.ASCIIEncoding m_asciiEncoding = new System.Text.ASCIIEncoding(); | 52 | private static System.Text.ASCIIEncoding m_asciiEncoding = new System.Text.ASCIIEncoding(); |
53 | 53 | ||
54 | private Scene m_scene; | 54 | private Scene m_scene; |
55 | private Stream m_loadStream; | 55 | private Stream m_loadStream; |
56 | private string m_errorMessage; | 56 | private string m_errorMessage; |
57 | |||
58 | /// <value> | ||
59 | /// Should the archive being loaded be merged with what is already on the region? | ||
60 | /// </value> | ||
61 | private bool m_merge; | ||
57 | 62 | ||
58 | /// <summary> | 63 | /// <summary> |
59 | /// Used to cache lookups for valid uuids. | 64 | /// Used to cache lookups for valid uuids. |
60 | /// </summary> | 65 | /// </summary> |
61 | private IDictionary<UUID, bool> m_validUserUuids = new Dictionary<UUID, bool>(); | 66 | private IDictionary<UUID, bool> m_validUserUuids = new Dictionary<UUID, bool>(); |
62 | 67 | ||
63 | public ArchiveReadRequest(Scene scene, string loadPath) | 68 | public ArchiveReadRequest(Scene scene, string loadPath, bool merge) |
64 | { | 69 | { |
65 | m_scene = scene; | 70 | m_scene = scene; |
66 | m_loadStream = new GZipStream(GetStream(loadPath), CompressionMode.Decompress); | 71 | m_loadStream = new GZipStream(GetStream(loadPath), CompressionMode.Decompress); |
67 | m_errorMessage = String.Empty; | 72 | m_errorMessage = String.Empty; |
73 | m_merge = merge; | ||
68 | } | 74 | } |
69 | 75 | ||
70 | public ArchiveReadRequest(Scene scene, Stream loadStream) | 76 | public ArchiveReadRequest(Scene scene, Stream loadStream, bool merge) |
71 | { | 77 | { |
72 | m_scene = scene; | 78 | m_scene = scene; |
73 | m_loadStream = loadStream; | 79 | m_loadStream = loadStream; |
80 | m_merge = merge; | ||
74 | } | 81 | } |
75 | 82 | ||
76 | /// <summary> | 83 | /// <summary> |
@@ -92,8 +99,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
92 | { | 99 | { |
93 | TarArchiveReader archive = new TarArchiveReader(m_loadStream); | 100 | TarArchiveReader archive = new TarArchiveReader(m_loadStream); |
94 | 101 | ||
95 | //AssetsDearchiver dearchiver = new AssetsDearchiver(m_scene.AssetCache); | ||
96 | |||
97 | string filePath = "ERROR"; | 102 | string filePath = "ERROR"; |
98 | 103 | ||
99 | byte[] data; | 104 | byte[] data; |
@@ -103,6 +108,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
103 | { | 108 | { |
104 | //m_log.DebugFormat( | 109 | //m_log.DebugFormat( |
105 | // "[ARCHIVER]: Successfully read {0} ({1} bytes)}", filePath, data.Length); | 110 | // "[ARCHIVER]: Successfully read {0} ({1} bytes)}", filePath, data.Length); |
111 | |||
106 | if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType) | 112 | if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType) |
107 | { | 113 | { |
108 | m_log.WarnFormat("[ARCHIVER]: Ignoring directory entry {0}", | 114 | m_log.WarnFormat("[ARCHIVER]: Ignoring directory entry {0}", |
@@ -112,11 +118,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
112 | { | 118 | { |
113 | serialisedSceneObjects.Add(m_asciiEncoding.GetString(data)); | 119 | serialisedSceneObjects.Add(m_asciiEncoding.GetString(data)); |
114 | } | 120 | } |
115 | // else if (filePath.Equals(ArchiveConstants.ASSETS_METADATA_PATH)) | ||
116 | // { | ||
117 | // string xml = m_asciiEncoding.GetString(data); | ||
118 | // dearchiver.AddAssetMetadata(xml); | ||
119 | // } | ||
120 | else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH)) | 121 | else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH)) |
121 | { | 122 | { |
122 | if (LoadAsset(filePath, data)) | 123 | if (LoadAsset(filePath, data)) |
@@ -124,11 +125,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
124 | else | 125 | else |
125 | failedAssetRestores++; | 126 | failedAssetRestores++; |
126 | } | 127 | } |
127 | else if (filePath.StartsWith(ArchiveConstants.TERRAINS_PATH)) | 128 | else if (!m_merge && filePath.StartsWith(ArchiveConstants.TERRAINS_PATH)) |
128 | { | 129 | { |
129 | LoadTerrain(filePath, data); | 130 | LoadTerrain(filePath, data); |
130 | } | 131 | } |
131 | else if (filePath.StartsWith(ArchiveConstants.SETTINGS_PATH)) | 132 | else if (!m_merge && filePath.StartsWith(ArchiveConstants.SETTINGS_PATH)) |
132 | { | 133 | { |
133 | LoadRegionSettings(filePath, data); | 134 | LoadRegionSettings(filePath, data); |
134 | } | 135 | } |
@@ -155,8 +156,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
155 | m_errorMessage += String.Format("Failed to load {0} assets", failedAssetRestores); | 156 | m_errorMessage += String.Format("Failed to load {0} assets", failedAssetRestores); |
156 | } | 157 | } |
157 | 158 | ||
158 | m_log.Info("[ARCHIVER]: Clearing all existing scene objects"); | 159 | if (!m_merge) |
159 | m_scene.DeleteAllSceneObjects(); | 160 | { |
161 | m_log.Info("[ARCHIVER]: Clearing all existing scene objects"); | ||
162 | m_scene.DeleteAllSceneObjects(); | ||
163 | } | ||
160 | 164 | ||
161 | // Reload serialized prims | 165 | // Reload serialized prims |
162 | m_log.InfoFormat("[ARCHIVER]: Loading {0} scene objects. Please wait.", serialisedSceneObjects.Count); | 166 | m_log.InfoFormat("[ARCHIVER]: Loading {0} scene objects. Please wait.", serialisedSceneObjects.Count); |
@@ -182,13 +186,13 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
182 | 186 | ||
183 | foreach (SceneObjectPart part in sceneObject.Children.Values) | 187 | foreach (SceneObjectPart part in sceneObject.Children.Values) |
184 | { | 188 | { |
185 | if (!resolveUserUuid(part.CreatorID)) | 189 | if (!ResolveUserUuid(part.CreatorID)) |
186 | part.CreatorID = masterAvatarId; | 190 | part.CreatorID = masterAvatarId; |
187 | 191 | ||
188 | if (!resolveUserUuid(part.OwnerID)) | 192 | if (!ResolveUserUuid(part.OwnerID)) |
189 | part.OwnerID = masterAvatarId; | 193 | part.OwnerID = masterAvatarId; |
190 | 194 | ||
191 | if (!resolveUserUuid(part.LastOwnerID)) | 195 | if (!ResolveUserUuid(part.LastOwnerID)) |
192 | part.LastOwnerID = masterAvatarId; | 196 | part.LastOwnerID = masterAvatarId; |
193 | 197 | ||
194 | // And zap any troublesome sit target information | 198 | // And zap any troublesome sit target information |
@@ -201,11 +205,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
201 | TaskInventoryDictionary inv = part.TaskInventory; | 205 | TaskInventoryDictionary inv = part.TaskInventory; |
202 | foreach (KeyValuePair<UUID, TaskInventoryItem> kvp in inv) | 206 | foreach (KeyValuePair<UUID, TaskInventoryItem> kvp in inv) |
203 | { | 207 | { |
204 | if (!resolveUserUuid(kvp.Value.OwnerID)) | 208 | if (!ResolveUserUuid(kvp.Value.OwnerID)) |
205 | { | 209 | { |
206 | kvp.Value.OwnerID = masterAvatarId; | 210 | kvp.Value.OwnerID = masterAvatarId; |
207 | } | 211 | } |
208 | if (!resolveUserUuid(kvp.Value.CreatorID)) | 212 | if (!ResolveUserUuid(kvp.Value.CreatorID)) |
209 | { | 213 | { |
210 | kvp.Value.CreatorID = masterAvatarId; | 214 | kvp.Value.CreatorID = masterAvatarId; |
211 | } | 215 | } |
@@ -242,7 +246,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
242 | /// </summary> | 246 | /// </summary> |
243 | /// <param name="uuid"></param> | 247 | /// <param name="uuid"></param> |
244 | /// <returns></returns> | 248 | /// <returns></returns> |
245 | private bool resolveUserUuid(UUID uuid) | 249 | private bool ResolveUserUuid(UUID uuid) |
246 | { | 250 | { |
247 | if (!m_validUserUuids.ContainsKey(uuid)) | 251 | if (!m_validUserUuids.ContainsKey(uuid)) |
248 | { | 252 | { |
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs index c1f5b18..6259662 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs | |||
@@ -81,15 +81,25 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
81 | 81 | ||
82 | public void DearchiveRegion(string loadPath) | 82 | public void DearchiveRegion(string loadPath) |
83 | { | 83 | { |
84 | DearchiveRegion(loadPath, false); | ||
85 | } | ||
86 | |||
87 | public void DearchiveRegion(string loadPath, bool merge) | ||
88 | { | ||
84 | m_log.InfoFormat( | 89 | m_log.InfoFormat( |
85 | "[ARCHIVER]: Loading archive to region {0} from {1}", m_scene.RegionInfo.RegionName, loadPath); | 90 | "[ARCHIVER]: Loading archive to region {0} from {1}", m_scene.RegionInfo.RegionName, loadPath); |
86 | 91 | ||
87 | new ArchiveReadRequest(m_scene, loadPath).DearchiveRegion(); | 92 | new ArchiveReadRequest(m_scene, loadPath, merge).DearchiveRegion(); |
88 | } | 93 | } |
89 | 94 | ||
90 | public void DearchiveRegion(Stream loadStream) | 95 | public void DearchiveRegion(Stream loadStream) |
91 | { | 96 | { |
92 | new ArchiveReadRequest(m_scene, loadStream).DearchiveRegion(); | 97 | DearchiveRegion(loadStream, false); |
93 | } | 98 | } |
99 | |||
100 | public void DearchiveRegion(Stream loadStream, bool merge) | ||
101 | { | ||
102 | new ArchiveReadRequest(m_scene, loadStream, merge).DearchiveRegion(); | ||
103 | } | ||
94 | } | 104 | } |
95 | } | 105 | } |
diff --git a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs index 77a3044..f201e74 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs | |||
@@ -167,14 +167,13 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests | |||
167 | [Test] | 167 | [Test] |
168 | public void TestLoadOarV0p2() | 168 | public void TestLoadOarV0p2() |
169 | { | 169 | { |
170 | log4net.Config.XmlConfigurator.Configure(); | 170 | //log4net.Config.XmlConfigurator.Configure(); |
171 | 171 | ||
172 | MemoryStream archiveWriteStream = new MemoryStream(); | 172 | MemoryStream archiveWriteStream = new MemoryStream(); |
173 | TarArchiveWriter tar = new TarArchiveWriter(); | 173 | TarArchiveWriter tar = new TarArchiveWriter(); |
174 | 174 | ||
175 | tar.AddFile(ArchiveConstants.CONTROL_FILE_PATH, ArchiveWriteRequestExecution.Create0p2ControlFile()); | 175 | tar.AddFile(ArchiveConstants.CONTROL_FILE_PATH, ArchiveWriteRequestExecution.Create0p2ControlFile()); |
176 | 176 | ||
177 | UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000020"); | ||
178 | string part1Name = "object1"; | 177 | string part1Name = "object1"; |
179 | PrimitiveBaseShape shape = PrimitiveBaseShape.CreateCylinder(); | 178 | PrimitiveBaseShape shape = PrimitiveBaseShape.CreateCylinder(); |
180 | Vector3 groupPosition = new Vector3(90, 80, 70); | 179 | Vector3 groupPosition = new Vector3(90, 80, 70); |
@@ -216,5 +215,84 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests | |||
216 | Assert.That( | 215 | Assert.That( |
217 | object1PartLoaded.OffsetPosition, Is.EqualTo(offsetPosition), "object1 offset position not equal"); | 216 | object1PartLoaded.OffsetPosition, Is.EqualTo(offsetPosition), "object1 offset position not equal"); |
218 | } | 217 | } |
218 | |||
219 | /// <summary> | ||
220 | /// Test merging a V0.2 OpenSim Region Archive into an existing scene | ||
221 | /// </summary> | ||
222 | [Test] | ||
223 | public void TestMergeOarV0p2() | ||
224 | { | ||
225 | log4net.Config.XmlConfigurator.Configure(); | ||
226 | |||
227 | MemoryStream archiveWriteStream = new MemoryStream(); | ||
228 | |||
229 | string part2Name = "objectMerge"; | ||
230 | PrimitiveBaseShape part2Shape = PrimitiveBaseShape.CreateCylinder(); | ||
231 | Vector3 part2GroupPosition = new Vector3(90, 80, 70); | ||
232 | Quaternion part2RotationOffset = new Quaternion(60, 70, 80, 90); | ||
233 | Vector3 part2OffsetPosition = new Vector3(20, 25, 30); | ||
234 | |||
235 | // Create an oar file that we can use for the merge | ||
236 | { | ||
237 | ArchiverModule archiverModule = new ArchiverModule(); | ||
238 | SerialiserModule serialiserModule = new SerialiserModule(); | ||
239 | TerrainModule terrainModule = new TerrainModule(); | ||
240 | |||
241 | Scene scene = SceneSetupHelpers.SetupScene(); | ||
242 | SceneSetupHelpers.SetupSceneModules(scene, archiverModule, serialiserModule, terrainModule); | ||
243 | |||
244 | SceneObjectPart part2 | ||
245 | = new SceneObjectPart( | ||
246 | UUID.Zero, part2Shape, part2GroupPosition, part2RotationOffset, part2OffsetPosition); | ||
247 | part2.Name = part2Name; | ||
248 | SceneObjectGroup object2 = new SceneObjectGroup(part2); | ||
249 | |||
250 | scene.AddNewSceneObject(object2, false); | ||
251 | |||
252 | // Write out this scene | ||
253 | scene.EventManager.OnOarFileSaved += SaveCompleted; | ||
254 | archiverModule.ArchiveRegion(archiveWriteStream); | ||
255 | m_waitHandle.WaitOne(60000, true); | ||
256 | } | ||
257 | |||
258 | { | ||
259 | ArchiverModule archiverModule = new ArchiverModule(); | ||
260 | SerialiserModule serialiserModule = new SerialiserModule(); | ||
261 | TerrainModule terrainModule = new TerrainModule(); | ||
262 | |||
263 | Scene scene = SceneSetupHelpers.SetupScene(); | ||
264 | SceneSetupHelpers.SetupSceneModules(scene, archiverModule, serialiserModule, terrainModule); | ||
265 | |||
266 | string part1Name = "objectExisting"; | ||
267 | PrimitiveBaseShape part1Shape = PrimitiveBaseShape.CreateCylinder(); | ||
268 | Vector3 part1GroupPosition = new Vector3(80, 70, 60); | ||
269 | Quaternion part1RotationOffset = new Quaternion(50, 60, 70, 80); | ||
270 | Vector3 part1OffsetPosition = new Vector3(15, 20, 25); | ||
271 | |||
272 | SceneObjectPart part1 | ||
273 | = new SceneObjectPart( | ||
274 | UUID.Zero, part1Shape, part1GroupPosition, part1RotationOffset, part1OffsetPosition); | ||
275 | part1.Name = part1Name; | ||
276 | SceneObjectGroup object1 = new SceneObjectGroup(part1); | ||
277 | |||
278 | scene.AddNewSceneObject(object1, false); | ||
279 | |||
280 | // Merge in the archive we created earlier | ||
281 | byte[] archive = archiveWriteStream.ToArray(); | ||
282 | MemoryStream archiveReadStream = new MemoryStream(archive); | ||
283 | |||
284 | archiverModule.DearchiveRegion(archiveReadStream, true); | ||
285 | |||
286 | SceneObjectPart object1Existing = scene.GetSceneObjectPart(part1Name); | ||
287 | Assert.That(object1Existing, Is.Not.Null, "object1 was not present after merge"); | ||
288 | Assert.That(object1Existing.Name, Is.EqualTo(part1Name), "object1 names not identical after merge"); | ||
289 | Assert.That(object1Existing.GroupPosition, Is.EqualTo(part1GroupPosition), "object1 group position not equal after merge"); | ||
290 | |||
291 | SceneObjectPart object2PartMerged = scene.GetSceneObjectPart(part2Name); | ||
292 | Assert.That(object2PartMerged, Is.Not.Null, "object2 was not present after merge"); | ||
293 | Assert.That(object2PartMerged.Name, Is.EqualTo(part2Name), "object2 names not identical after merge"); | ||
294 | Assert.That(object2PartMerged.GroupPosition, Is.EqualTo(part2GroupPosition), "object2 group position not equal after merge"); | ||
295 | } | ||
296 | } | ||
219 | } | 297 | } |
220 | } \ No newline at end of file | 298 | } \ No newline at end of file |
diff --git a/OpenSim/Region/Framework/Interfaces/IRegionArchiverModule.cs b/OpenSim/Region/Framework/Interfaces/IRegionArchiverModule.cs index 97afe8d..601b83e 100644 --- a/OpenSim/Region/Framework/Interfaces/IRegionArchiverModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IRegionArchiverModule.cs | |||
@@ -55,7 +55,7 @@ namespace OpenSim.Region.Framework.Interfaces | |||
55 | void ArchiveRegion(Stream saveStream); | 55 | void ArchiveRegion(Stream saveStream); |
56 | 56 | ||
57 | /// <summary> | 57 | /// <summary> |
58 | /// Dearchive the given region archive into the scene | 58 | /// Dearchive the given region archive. This replaces the existing scene. |
59 | /// </summary> | 59 | /// </summary> |
60 | /// | 60 | /// |
61 | /// If you want notification of when it has completed then subscribe to the EventManager.OnOarFileLoaded event. | 61 | /// If you want notification of when it has completed then subscribe to the EventManager.OnOarFileLoaded event. |
@@ -64,12 +64,38 @@ namespace OpenSim.Region.Framework.Interfaces | |||
64 | void DearchiveRegion(string loadPath); | 64 | void DearchiveRegion(string loadPath); |
65 | 65 | ||
66 | /// <summary> | 66 | /// <summary> |
67 | /// Dearchive a region from a stream. | 67 | /// Dearchive the given region archive. This replaces the existing scene. |
68 | /// </summary> | ||
69 | /// | ||
70 | /// If you want notification of when it has completed then subscribe to the EventManager.OnOarFileLoaded event. | ||
71 | /// | ||
72 | /// <param name="loadPath"></param> | ||
73 | /// <param name="merge"> | ||
74 | /// If true, the loaded region merges with the existing one rather than replacing it. Any terrain or region | ||
75 | /// settings in the archive will be ignored. | ||
76 | /// </param> | ||
77 | void DearchiveRegion(string loadPath, bool merge); | ||
78 | |||
79 | /// <summary> | ||
80 | /// Dearchive a region from a stream. This replaces the existing scene. | ||
68 | /// </summary> | 81 | /// </summary> |
69 | /// | 82 | /// |
70 | /// If you want notification of when it has completed then subscribe to the EventManager.OnOarFileLoaded event. | 83 | /// If you want notification of when it has completed then subscribe to the EventManager.OnOarFileLoaded event. |
71 | /// | 84 | /// |
72 | /// <param name="loadStream"></param> | 85 | /// <param name="loadStream"></param> |
73 | void DearchiveRegion(Stream loadStream); | 86 | void DearchiveRegion(Stream loadStream); |
87 | |||
88 | /// <summary> | ||
89 | /// Dearchive a region from a stream. This replaces the existing scene. | ||
90 | /// </summary> | ||
91 | /// | ||
92 | /// If you want notification of when it has completed then subscribe to the EventManager.OnOarFileLoaded event. | ||
93 | /// | ||
94 | /// <param name="loadStream"></param> | ||
95 | /// <param name="merge"> | ||
96 | /// If true, the loaded region merges with the existing one rather than replacing it. Any terrain or region | ||
97 | /// settings in the archive will be ignored. | ||
98 | /// </param> | ||
99 | void DearchiveRegion(Stream loadStream, bool merge); | ||
74 | } | 100 | } |
75 | } | 101 | } |