opensim-development – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 eva 1 /*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27  
28 using System;
29 using System.Collections.Generic;
30 using System.IO;
31 using System.IO.Compression;
32 using System.Net;
33 using System.Reflection;
34 using System.Text;
35 using System.Xml;
36 using log4net;
37 using OpenMetaverse;
38 using OpenSim.Framework;
39 using OpenSim.Framework.Serialization;
40 using OpenSim.Framework.Serialization.External;
41 using OpenSim.Region.CoreModules.World.Terrain;
42 using OpenSim.Region.Framework.Interfaces;
43 using OpenSim.Region.Framework.Scenes;
44 using OpenSim.Region.Framework.Scenes.Serialization;
45 using OpenSim.Services.Interfaces;
46 using System.Threading;
47  
48 namespace OpenSim.Region.CoreModules.World.Archiver
49 {
50 /// <summary>
51 /// Handles an individual archive read request
52 /// </summary>
53 public class ArchiveReadRequest
54 {
55 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
56  
57 /// <summary>
58 /// Contains data used while dearchiving a single scene.
59 /// </summary>
60 private class DearchiveContext
61 {
62 public Scene Scene { get; set; }
63  
64 public List<string> SerialisedSceneObjects { get; set; }
65  
66 public List<string> SerialisedParcels { get; set; }
67  
68 public List<SceneObjectGroup> SceneObjects { get; set; }
69  
70 public DearchiveContext(Scene scene)
71 {
72 Scene = scene;
73 SerialisedSceneObjects = new List<string>();
74 SerialisedParcels = new List<string>();
75 SceneObjects = new List<SceneObjectGroup>();
76 }
77 }
78  
79  
80 /// <summary>
81 /// The maximum major version of OAR that we can read. Minor versions shouldn't need a max number since version
82 /// bumps here should be compatible.
83 /// </summary>
84 public static int MAX_MAJOR_VERSION = 1;
85  
86 /// <summary>
87 /// Has the control file been loaded for this archive?
88 /// </summary>
89 public bool ControlFileLoaded { get; private set; }
90  
91 protected string m_loadPath;
92 protected Scene m_rootScene;
93 protected Stream m_loadStream;
94 protected Guid m_requestId;
95 protected string m_errorMessage;
96  
97 /// <value>
98 /// Should the archive being loaded be merged with what is already on the region?
99 /// Merging usually suppresses terrain and parcel loading
100 /// </value>
101 protected bool m_merge;
102  
103 /// <value>
104 /// If true, force the loading of terrain from the oar file
105 /// </value>
106 protected bool m_forceTerrain;
107  
108 /// <value>
109 /// If true, force the loading of parcels from the oar file
110 /// </value>
111 protected bool m_forceParcels;
112  
113 /// <value>
114 /// Should we ignore any assets when reloading the archive?
115 /// </value>
116 protected bool m_skipAssets;
117  
118 /// <value>
119 /// Displacement added to each object as it is added to the world
120 /// </value>
121 protected Vector3 m_displacement = Vector3.Zero;
122  
123 /// <value>
124 /// Rotation (in radians) to apply to the objects as they are loaded.
125 /// </value>
126 protected float m_rotation = 0f;
127  
128 /// <value>
129 /// Center around which to apply the rotation relative to the origional oar position
130 /// </value>
131 protected Vector3 m_rotationCenter = new Vector3(Constants.RegionSize / 2f, Constants.RegionSize / 2f, 0f);
132  
133 protected bool m_noObjects = false;
134  
135 /// <summary>
136 /// Used to cache lookups for valid uuids.
137 /// </summary>
138 private IDictionary<UUID, bool> m_validUserUuids = new Dictionary<UUID, bool>();
139  
140 private IUserManagement m_UserMan;
141 private IUserManagement UserManager
142 {
143 get
144 {
145 if (m_UserMan == null)
146 {
147 m_UserMan = m_rootScene.RequestModuleInterface<IUserManagement>();
148 }
149 return m_UserMan;
150 }
151 }
152  
153 /// <summary>
154 /// Used to cache lookups for valid groups.
155 /// </summary>
156 private IDictionary<UUID, bool> m_validGroupUuids = new Dictionary<UUID, bool>();
157  
158 private IGroupsModule m_groupsModule;
159  
160 private IAssetService m_assetService = null;
161  
162  
163 public ArchiveReadRequest(Scene scene, string loadPath, Guid requestId, Dictionary<string,object>options)
164 {
165 m_rootScene = scene;
166  
167 m_loadPath = loadPath;
168 try
169 {
170 m_loadStream = new GZipStream(ArchiveHelpers.GetStream(loadPath), CompressionMode.Decompress);
171 }
172 catch (EntryPointNotFoundException e)
173 {
174 m_log.ErrorFormat(
175 "[ARCHIVER]: Mismatch between Mono and zlib1g library version when trying to create compression stream."
176 + "If you've manually installed Mono, have you appropriately updated zlib1g as well?");
177 m_log.Error(e);
178 }
179  
180 m_errorMessage = String.Empty;
181 m_merge = options.ContainsKey("merge");
182 m_forceTerrain = options.ContainsKey("force-terrain");
183 m_forceParcels = options.ContainsKey("force-parcels");
184 m_noObjects = options.ContainsKey("no-objects");
185 m_skipAssets = options.ContainsKey("skipAssets");
186 m_requestId = requestId;
187 m_displacement = options.ContainsKey("displacement") ? (Vector3)options["displacement"] : Vector3.Zero;
188 m_rotation = options.ContainsKey("rotation") ? (float)options["rotation"] : 0f;
189 m_rotationCenter = options.ContainsKey("rotation-center") ? (Vector3)options["rotation-center"]
190 : new Vector3(scene.RegionInfo.RegionSizeX / 2f, scene.RegionInfo.RegionSizeY / 2f, 0f);
191  
192 // Zero can never be a valid user id
193 m_validUserUuids[UUID.Zero] = false;
194  
195 m_groupsModule = m_rootScene.RequestModuleInterface<IGroupsModule>();
196 m_assetService = m_rootScene.AssetService;
197 }
198  
199 public ArchiveReadRequest(Scene scene, Stream loadStream, Guid requestId, Dictionary<string, object>options)
200 {
201 m_rootScene = scene;
202 m_loadPath = null;
203 m_loadStream = loadStream;
204 m_skipAssets = options.ContainsKey("skipAssets");
205 m_merge = options.ContainsKey("merge");
206 m_requestId = requestId;
207  
208 // Zero can never be a valid user id
209 m_validUserUuids[UUID.Zero] = false;
210  
211 m_groupsModule = m_rootScene.RequestModuleInterface<IGroupsModule>();
212 m_assetService = m_rootScene.AssetService;
213 }
214  
215 /// <summary>
216 /// Dearchive the region embodied in this request.
217 /// </summary>
218 public void DearchiveRegion()
219 {
220 int successfulAssetRestores = 0;
221 int failedAssetRestores = 0;
222  
223 DearchiveScenesInfo dearchivedScenes;
224  
225 // We dearchive all the scenes at once, because the files in the TAR archive might be mixed.
226 // Therefore, we have to keep track of the dearchive context of all the scenes.
227 Dictionary<UUID, DearchiveContext> sceneContexts = new Dictionary<UUID, DearchiveContext>();
228  
229 string fullPath = "NONE";
230 TarArchiveReader archive = null;
231 byte[] data;
232 TarArchiveReader.TarEntryType entryType;
233  
234 try
235 {
236 FindAndLoadControlFile(out archive, out dearchivedScenes);
237  
238 while ((data = archive.ReadEntry(out fullPath, out entryType)) != null)
239 {
240 //m_log.DebugFormat(
241 // "[ARCHIVER]: Successfully read {0} ({1} bytes)", filePath, data.Length);
242  
243 if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType)
244 continue;
245  
246  
247 // Find the scene that this file belongs to
248  
249 Scene scene;
250 string filePath;
251 if (!dearchivedScenes.GetRegionFromPath(fullPath, out scene, out filePath))
252 continue; // this file belongs to a region that we're not loading
253  
254 DearchiveContext sceneContext = null;
255 if (scene != null)
256 {
257 if (!sceneContexts.TryGetValue(scene.RegionInfo.RegionID, out sceneContext))
258 {
259 sceneContext = new DearchiveContext(scene);
260 sceneContexts.Add(scene.RegionInfo.RegionID, sceneContext);
261 }
262 }
263  
264  
265 // Process the file
266  
267 if (filePath.StartsWith(ArchiveConstants.OBJECTS_PATH) && !m_noObjects)
268 {
269 sceneContext.SerialisedSceneObjects.Add(Encoding.UTF8.GetString(data));
270 }
271 else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH) && !m_skipAssets)
272 {
273 if (LoadAsset(filePath, data))
274 successfulAssetRestores++;
275 else
276 failedAssetRestores++;
277  
278 if ((successfulAssetRestores + failedAssetRestores) % 250 == 0)
279 m_log.Debug("[ARCHIVER]: Loaded " + successfulAssetRestores + " assets and failed to load " + failedAssetRestores + " assets...");
280 }
281 else if (filePath.StartsWith(ArchiveConstants.TERRAINS_PATH) && (!m_merge || m_forceTerrain))
282 {
283 LoadTerrain(scene, filePath, data);
284 }
285 else if (!m_merge && filePath.StartsWith(ArchiveConstants.SETTINGS_PATH))
286 {
287 LoadRegionSettings(scene, filePath, data, dearchivedScenes);
288 }
289 else if (filePath.StartsWith(ArchiveConstants.LANDDATA_PATH) && (!m_merge || m_forceParcels))
290 {
291 sceneContext.SerialisedParcels.Add(Encoding.UTF8.GetString(data));
292 }
293 else if (filePath == ArchiveConstants.CONTROL_FILE_PATH)
294 {
295 // Ignore, because we already read the control file
296 }
297 }
298  
299 //m_log.Debug("[ARCHIVER]: Reached end of archive");
300 }
301 catch (Exception e)
302 {
303 m_log.Error(
304 String.Format("[ARCHIVER]: Aborting load with error in archive file {0} ", fullPath), e);
305 m_errorMessage += e.ToString();
306 m_rootScene.EventManager.TriggerOarFileLoaded(m_requestId, new List<UUID>(), m_errorMessage);
307 return;
308 }
309 finally
310 {
311 if (archive != null)
312 archive.Close();
313 }
314  
315 if (!m_skipAssets)
316 {
317 m_log.InfoFormat("[ARCHIVER]: Restored {0} assets", successfulAssetRestores);
318  
319 if (failedAssetRestores > 0)
320 {
321 m_log.ErrorFormat("[ARCHIVER]: Failed to load {0} assets", failedAssetRestores);
322 m_errorMessage += String.Format("Failed to load {0} assets", failedAssetRestores);
323 }
324 }
325  
326 foreach (DearchiveContext sceneContext in sceneContexts.Values)
327 {
328 m_log.InfoFormat("[ARCHIVER]: Loading region {0}", sceneContext.Scene.RegionInfo.RegionName);
329  
330 if (!m_merge)
331 {
332 m_log.Info("[ARCHIVER]: Clearing all existing scene objects");
333 sceneContext.Scene.DeleteAllSceneObjects();
334 }
335  
336 try
337 {
338 LoadParcels(sceneContext.Scene, sceneContext.SerialisedParcels);
339 LoadObjects(sceneContext.Scene, sceneContext.SerialisedSceneObjects, sceneContext.SceneObjects);
340  
341 // Inform any interested parties that the region has changed. We waited until now so that all
342 // of the region's objects will be loaded when we send this notification.
343 IEstateModule estateModule = sceneContext.Scene.RequestModuleInterface<IEstateModule>();
344 if (estateModule != null)
345 estateModule.TriggerRegionInfoChange();
346 }
347 catch (Exception e)
348 {
349 m_log.Error("[ARCHIVER]: Error loading parcels or objects ", e);
350 m_errorMessage += e.ToString();
351 m_rootScene.EventManager.TriggerOarFileLoaded(m_requestId, new List<UUID>(), m_errorMessage);
352 return;
353 }
354 }
355  
356 // Start the scripts. We delayed this because we want the OAR to finish loading ASAP, so
357 // that users can enter the scene. If we allow the scripts to start in the loop above
358 // then they significantly increase the time until the OAR finishes loading.
359 Util.FireAndForget(delegate(object o)
360 {
361 Thread.Sleep(15000);
362 m_log.Info("[ARCHIVER]: Starting scripts in scene objects");
363  
364 foreach (DearchiveContext sceneContext in sceneContexts.Values)
365 {
366 foreach (SceneObjectGroup sceneObject in sceneContext.SceneObjects)
367 {
368 sceneObject.CreateScriptInstances(0, false, sceneContext.Scene.DefaultScriptEngine, 0); // StateSource.RegionStart
369 sceneObject.ResumeScripts();
370 }
371  
372 sceneContext.SceneObjects.Clear();
373 }
374 });
375  
376 m_log.InfoFormat("[ARCHIVER]: Successfully loaded archive");
377  
378 m_rootScene.EventManager.TriggerOarFileLoaded(m_requestId, dearchivedScenes.GetLoadedScenes(), m_errorMessage);
379 }
380  
381 /// <summary>
382 /// Searches through the files in the archive for the control file, and reads it.
383 /// We must read the control file first, in order to know which regions are available.
384 /// </summary>
385 /// <remarks>
386 /// In most cases the control file *is* first, since that's how we create archives. However,
387 /// it's possible that someone rewrote the archive externally so we can't rely on this fact.
388 /// </remarks>
389 /// <param name="archive"></param>
390 /// <param name="dearchivedScenes"></param>
391 private void FindAndLoadControlFile(out TarArchiveReader archive, out DearchiveScenesInfo dearchivedScenes)
392 {
393 archive = new TarArchiveReader(m_loadStream);
394 dearchivedScenes = new DearchiveScenesInfo();
395  
396 string filePath;
397 byte[] data;
398 TarArchiveReader.TarEntryType entryType;
399 bool firstFile = true;
400  
401 while ((data = archive.ReadEntry(out filePath, out entryType)) != null)
402 {
403 if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType)
404 continue;
405  
406 if (filePath == ArchiveConstants.CONTROL_FILE_PATH)
407 {
408 LoadControlFile(filePath, data, dearchivedScenes);
409  
410 // Find which scenes are available in the simulator
411 ArchiveScenesGroup simulatorScenes = new ArchiveScenesGroup();
412 SceneManager.Instance.ForEachScene(delegate(Scene scene2)
413 {
414 simulatorScenes.AddScene(scene2);
415 });
416 simulatorScenes.CalcSceneLocations();
417 dearchivedScenes.SetSimulatorScenes(m_rootScene, simulatorScenes);
418  
419 // If the control file wasn't the first file then reset the read pointer
420 if (!firstFile)
421 {
422 m_log.Warn("Control file wasn't the first file in the archive");
423 if (m_loadStream.CanSeek)
424 {
425 m_loadStream.Seek(0, SeekOrigin.Begin);
426 }
427 else if (m_loadPath != null)
428 {
429 archive.Close();
430 archive = null;
431 m_loadStream.Close();
432 m_loadStream = null;
433 m_loadStream = new GZipStream(ArchiveHelpers.GetStream(m_loadPath), CompressionMode.Decompress);
434 archive = new TarArchiveReader(m_loadStream);
435 }
436 else
437 {
438 // There isn't currently a scenario where this happens, but it's best to add a check just in case
439 throw new Exception("Error reading archive: control file wasn't the first file, and the input stream doesn't allow seeking");
440 }
441 }
442  
443 return;
444 }
445  
446 firstFile = false;
447 }
448  
449 throw new Exception("Control file not found");
450 }
451  
452 /// <summary>
453 /// Load serialized scene objects.
454 /// </summary>
455 protected void LoadObjects(Scene scene, List<string> serialisedSceneObjects, List<SceneObjectGroup> sceneObjects)
456 {
457 // Reload serialized prims
458 m_log.InfoFormat("[ARCHIVER]: Loading {0} scene objects. Please wait.", serialisedSceneObjects.Count);
459  
460 OpenMetaverse.Quaternion rot = OpenMetaverse.Quaternion.CreateFromAxisAngle(0, 0, 1, m_rotation);
461  
462 UUID oldTelehubUUID = scene.RegionInfo.RegionSettings.TelehubObject;
463  
464 IRegionSerialiserModule serialiser = scene.RequestModuleInterface<IRegionSerialiserModule>();
465 int sceneObjectsLoadedCount = 0;
466  
467 foreach (string serialisedSceneObject in serialisedSceneObjects)
468 {
469 /*
470 m_log.DebugFormat("[ARCHIVER]: Loading xml with raw size {0}", serialisedSceneObject.Length);
471  
472 // Really large xml files (multi megabyte) appear to cause
473 // memory problems
474 // when loading the xml. But don't enable this check yet
475  
476 if (serialisedSceneObject.Length > 5000000)
477 {
478 m_log.Error("[ARCHIVER]: Ignoring xml since size > 5000000);");
479 continue;
480 }
481 */
482  
483 SceneObjectGroup sceneObject = serialiser.DeserializeGroupFromXml2(serialisedSceneObject);
484  
485 // Happily this does not do much to the object since it hasn't been added to the scene yet
486 if (sceneObject.AttachmentPoint == 0)
487 {
488 if (m_displacement != Vector3.Zero || m_rotation != 0f)
489 {
490 Vector3 pos = sceneObject.AbsolutePosition;
491 if (m_rotation != 0f)
492 {
493 // Rotate the object
494 sceneObject.RootPart.RotationOffset = rot * sceneObject.GroupRotation;
495 // Get object position relative to rotation axis
496 Vector3 offset = pos - m_rotationCenter;
497 // Rotate the object position
498 offset *= rot;
499 // Restore the object position back to relative to the region
500 pos = m_rotationCenter + offset;
501 }
502 if (m_displacement != Vector3.Zero)
503 {
504 pos += m_displacement;
505 }
506 sceneObject.AbsolutePosition = pos;
507 }
508 }
509  
510  
511 bool isTelehub = (sceneObject.UUID == oldTelehubUUID) && (oldTelehubUUID != UUID.Zero);
512  
513 // For now, give all incoming scene objects new uuids. This will allow scenes to be cloned
514 // on the same region server and multiple examples a single object archive to be imported
515 // to the same scene (when this is possible).
516 sceneObject.ResetIDs();
517  
518 if (isTelehub)
519 {
520 // Change the Telehub Object to the new UUID
521 scene.RegionInfo.RegionSettings.TelehubObject = sceneObject.UUID;
522 scene.RegionInfo.RegionSettings.Save();
523 oldTelehubUUID = UUID.Zero;
524 }
525  
526 // Try to retain the original creator/owner/lastowner if their uuid is present on this grid
527 // or creator data is present. Otherwise, use the estate owner instead.
528 foreach (SceneObjectPart part in sceneObject.Parts)
529 {
530 if (string.IsNullOrEmpty(part.CreatorData))
531 {
532 if (!ResolveUserUuid(scene, part.CreatorID))
533 part.CreatorID = scene.RegionInfo.EstateSettings.EstateOwner;
534 }
535 if (UserManager != null)
536 UserManager.AddUser(part.CreatorID, part.CreatorData);
537  
538 if (!ResolveUserUuid(scene, part.OwnerID))
539 part.OwnerID = scene.RegionInfo.EstateSettings.EstateOwner;
540  
541 if (!ResolveUserUuid(scene, part.LastOwnerID))
542 part.LastOwnerID = scene.RegionInfo.EstateSettings.EstateOwner;
543  
544 if (!ResolveGroupUuid(part.GroupID))
545 part.GroupID = UUID.Zero;
546  
547 // And zap any troublesome sit target information
548 // part.SitTargetOrientation = new Quaternion(0, 0, 0, 1);
549 // part.SitTargetPosition = new Vector3(0, 0, 0);
550  
551 // Fix ownership/creator of inventory items
552 // Not doing so results in inventory items
553 // being no copy/no mod for everyone
554 lock (part.TaskInventory)
555 {
556 TaskInventoryDictionary inv = part.TaskInventory;
557 foreach (KeyValuePair<UUID, TaskInventoryItem> kvp in inv)
558 {
559 if (!ResolveUserUuid(scene, kvp.Value.OwnerID))
560 {
561 kvp.Value.OwnerID = scene.RegionInfo.EstateSettings.EstateOwner;
562 }
563  
564 if (string.IsNullOrEmpty(kvp.Value.CreatorData))
565 {
566 if (!ResolveUserUuid(scene, kvp.Value.CreatorID))
567 kvp.Value.CreatorID = scene.RegionInfo.EstateSettings.EstateOwner;
568 }
569  
570 if (UserManager != null)
571 UserManager.AddUser(kvp.Value.CreatorID, kvp.Value.CreatorData);
572  
573 if (!ResolveGroupUuid(kvp.Value.GroupID))
574 kvp.Value.GroupID = UUID.Zero;
575 }
576 }
577 }
578  
579 if (scene.AddRestoredSceneObject(sceneObject, true, false))
580 {
581 sceneObjectsLoadedCount++;
582 sceneObject.CreateScriptInstances(0, false, scene.DefaultScriptEngine, 0);
583 sceneObject.ResumeScripts();
584 }
585 }
586  
587 m_log.InfoFormat("[ARCHIVER]: Restored {0} scene objects to the scene", sceneObjectsLoadedCount);
588  
589 int ignoredObjects = serialisedSceneObjects.Count - sceneObjectsLoadedCount;
590  
591 if (ignoredObjects > 0)
592 m_log.WarnFormat("[ARCHIVER]: Ignored {0} scene objects that already existed in the scene", ignoredObjects);
593  
594 if (oldTelehubUUID != UUID.Zero)
595 {
596 m_log.WarnFormat("Telehub object not found: {0}", oldTelehubUUID);
597 scene.RegionInfo.RegionSettings.TelehubObject = UUID.Zero;
598 scene.RegionInfo.RegionSettings.ClearSpawnPoints();
599 }
600 }
601  
602 /// <summary>
603 /// Load serialized parcels.
604 /// </summary>
605 /// <param name="scene"></param>
606 /// <param name="serialisedParcels"></param>
607 protected void LoadParcels(Scene scene, List<string> serialisedParcels)
608 {
609 // Reload serialized parcels
610 m_log.InfoFormat("[ARCHIVER]: Loading {0} parcels. Please wait.", serialisedParcels.Count);
611 List<LandData> landData = new List<LandData>();
612 foreach (string serialisedParcel in serialisedParcels)
613 {
614 LandData parcel = LandDataSerializer.Deserialize(serialisedParcel);
615  
616 if (m_displacement != Vector3.Zero)
617 {
618 Vector3 parcelDisp = new Vector3(m_displacement.X, m_displacement.Y, 0f);
619 parcel.AABBMin += parcelDisp;
620 parcel.AABBMax += parcelDisp;
621 }
622  
623 // Validate User and Group UUID's
624  
625 if (parcel.IsGroupOwned)
626 {
627 if (!ResolveGroupUuid(parcel.GroupID))
628 {
629 parcel.OwnerID = m_rootScene.RegionInfo.EstateSettings.EstateOwner;
630 parcel.GroupID = UUID.Zero;
631 parcel.IsGroupOwned = false;
632 }
633 }
634 else
635 {
636 if (!ResolveUserUuid(scene, parcel.OwnerID))
637 parcel.OwnerID = m_rootScene.RegionInfo.EstateSettings.EstateOwner;
638  
639 if (!ResolveGroupUuid(parcel.GroupID))
640 parcel.GroupID = UUID.Zero;
641 }
642  
643 List<LandAccessEntry> accessList = new List<LandAccessEntry>();
644 foreach (LandAccessEntry entry in parcel.ParcelAccessList)
645 {
646 if (ResolveUserUuid(scene, entry.AgentID))
647 accessList.Add(entry);
648 // else, drop this access rule
649 }
650 parcel.ParcelAccessList = accessList;
651  
652 // m_log.DebugFormat(
653 // "[ARCHIVER]: Adding parcel {0}, local id {1}, owner {2}, group {3}, isGroupOwned {4}, area {5}",
654 // parcel.Name, parcel.LocalID, parcel.OwnerID, parcel.GroupID, parcel.IsGroupOwned, parcel.Area);
655  
656 landData.Add(parcel);
657 }
658  
659 if (!m_merge)
660 {
661 bool setupDefaultParcel = (landData.Count == 0);
662 scene.LandChannel.Clear(setupDefaultParcel);
663 }
664  
665 scene.EventManager.TriggerIncomingLandDataFromStorage(landData);
666 m_log.InfoFormat("[ARCHIVER]: Restored {0} parcels.", landData.Count);
667 }
668  
669 /// <summary>
670 /// Look up the given user id to check whether it's one that is valid for this grid.
671 /// </summary>
672 /// <param name="scene"></param>
673 /// <param name="uuid"></param>
674 /// <returns></returns>
675 private bool ResolveUserUuid(Scene scene, UUID uuid)
676 {
677 lock (m_validUserUuids)
678 {
679 if (!m_validUserUuids.ContainsKey(uuid))
680 {
681 // Note: we call GetUserAccount() inside the lock because this UserID is likely
682 // to occur many times, and we only want to query the users service once.
683 UserAccount account = scene.UserAccountService.GetUserAccount(scene.RegionInfo.ScopeID, uuid);
684 m_validUserUuids.Add(uuid, account != null);
685 }
686  
687 return m_validUserUuids[uuid];
688 }
689 }
690  
691 /// <summary>
692 /// Look up the given group id to check whether it's one that is valid for this grid.
693 /// </summary>
694 /// <param name="uuid"></param>
695 /// <returns></returns>
696 private bool ResolveGroupUuid(UUID uuid)
697 {
698 if (uuid == UUID.Zero)
699 return true; // this means the object has no group
700  
701 lock (m_validGroupUuids)
702 {
703 if (!m_validGroupUuids.ContainsKey(uuid))
704 {
705 bool exists;
706 if (m_groupsModule == null)
707 {
708 exists = false;
709 }
710 else
711 {
712 // Note: we call GetGroupRecord() inside the lock because this GroupID is likely
713 // to occur many times, and we only want to query the groups service once.
714 exists = (m_groupsModule.GetGroupRecord(uuid) != null);
715 }
716 m_validGroupUuids.Add(uuid, exists);
717 }
718  
719 return m_validGroupUuids[uuid];
720 }
721 }
722  
723 /// Load an asset
724 /// </summary>
725 /// <param name="assetFilename"></param>
726 /// <param name="data"></param>
727 /// <returns>true if asset was successfully loaded, false otherwise</returns>
728 private bool LoadAsset(string assetPath, byte[] data)
729 {
730 // Right now we're nastily obtaining the UUID from the filename
731 string filename = assetPath.Remove(0, ArchiveConstants.ASSETS_PATH.Length);
732 int i = filename.LastIndexOf(ArchiveConstants.ASSET_EXTENSION_SEPARATOR);
733  
734 if (i == -1)
735 {
736 m_log.ErrorFormat(
737 "[ARCHIVER]: Could not find extension information in asset path {0} since it's missing the separator {1}. Skipping",
738 assetPath, ArchiveConstants.ASSET_EXTENSION_SEPARATOR);
739  
740 return false;
741 }
742  
743 string extension = filename.Substring(i);
744 string uuid = filename.Remove(filename.Length - extension.Length);
745  
746 if (m_assetService.GetMetadata(uuid) != null)
747 {
748 // m_log.DebugFormat("[ARCHIVER]: found existing asset {0}",uuid);
749 return true;
750 }
751  
752 if (ArchiveConstants.EXTENSION_TO_ASSET_TYPE.ContainsKey(extension))
753 {
754 sbyte assetType = ArchiveConstants.EXTENSION_TO_ASSET_TYPE[extension];
755  
756 if (assetType == (sbyte)AssetType.Unknown)
757 m_log.WarnFormat("[ARCHIVER]: Importing {0} byte asset {1} with unknown type", data.Length, uuid);
758  
759 //m_log.DebugFormat("[ARCHIVER]: Importing asset {0}, type {1}", uuid, assetType);
760  
761 AssetBase asset = new AssetBase(new UUID(uuid), String.Empty, assetType, UUID.Zero.ToString());
762 asset.Data = data;
763  
764 // We're relying on the asset service to do the sensible thing and not store the asset if it already
765 // exists.
766 m_assetService.Store(asset);
767  
768 /**
769 * Create layers on decode for image assets. This is likely to significantly increase the time to load archives so
770 * it might be best done when dearchive takes place on a separate thread
771 if (asset.Type=AssetType.Texture)
772 {
773 IJ2KDecoder cacheLayerDecode = scene.RequestModuleInterface<IJ2KDecoder>();
774 if (cacheLayerDecode != null)
775 cacheLayerDecode.syncdecode(asset.FullID, asset.Data);
776 }
777 */
778  
779 return true;
780 }
781 else
782 {
783 m_log.ErrorFormat(
784 "[ARCHIVER]: Tried to dearchive data with path {0} with an unknown type extension {1}",
785 assetPath, extension);
786  
787 return false;
788 }
789 }
790  
791 /// <summary>
792 /// Load region settings data
793 /// </summary>
794 /// <param name="scene"></param>
795 /// <param name="settingsPath"></param>
796 /// <param name="data"></param>
797 /// <param name="dearchivedScenes"></param>
798 /// <returns>
799 /// true if settings were loaded successfully, false otherwise
800 /// </returns>
801 private bool LoadRegionSettings(Scene scene, string settingsPath, byte[] data, DearchiveScenesInfo dearchivedScenes)
802 {
803 RegionSettings loadedRegionSettings;
804  
805 try
806 {
807 loadedRegionSettings = RegionSettingsSerializer.Deserialize(data);
808 }
809 catch (Exception e)
810 {
811 m_log.ErrorFormat(
812 "[ARCHIVER]: Could not parse region settings file {0}. Ignoring. Exception was {1}",
813 settingsPath, e);
814 return false;
815 }
816  
817 RegionSettings currentRegionSettings = scene.RegionInfo.RegionSettings;
818  
819 currentRegionSettings.AgentLimit = loadedRegionSettings.AgentLimit;
820 currentRegionSettings.AllowDamage = loadedRegionSettings.AllowDamage;
821 currentRegionSettings.AllowLandJoinDivide = loadedRegionSettings.AllowLandJoinDivide;
822 currentRegionSettings.AllowLandResell = loadedRegionSettings.AllowLandResell;
823 currentRegionSettings.BlockFly = loadedRegionSettings.BlockFly;
824 currentRegionSettings.BlockShowInSearch = loadedRegionSettings.BlockShowInSearch;
825 currentRegionSettings.BlockTerraform = loadedRegionSettings.BlockTerraform;
826 currentRegionSettings.DisableCollisions = loadedRegionSettings.DisableCollisions;
827 currentRegionSettings.DisablePhysics = loadedRegionSettings.DisablePhysics;
828 currentRegionSettings.DisableScripts = loadedRegionSettings.DisableScripts;
829 currentRegionSettings.Elevation1NE = loadedRegionSettings.Elevation1NE;
830 currentRegionSettings.Elevation1NW = loadedRegionSettings.Elevation1NW;
831 currentRegionSettings.Elevation1SE = loadedRegionSettings.Elevation1SE;
832 currentRegionSettings.Elevation1SW = loadedRegionSettings.Elevation1SW;
833 currentRegionSettings.Elevation2NE = loadedRegionSettings.Elevation2NE;
834 currentRegionSettings.Elevation2NW = loadedRegionSettings.Elevation2NW;
835 currentRegionSettings.Elevation2SE = loadedRegionSettings.Elevation2SE;
836 currentRegionSettings.Elevation2SW = loadedRegionSettings.Elevation2SW;
837 currentRegionSettings.FixedSun = loadedRegionSettings.FixedSun;
838 currentRegionSettings.SunPosition = loadedRegionSettings.SunPosition;
839 currentRegionSettings.ObjectBonus = loadedRegionSettings.ObjectBonus;
840 currentRegionSettings.RestrictPushing = loadedRegionSettings.RestrictPushing;
841 currentRegionSettings.TerrainLowerLimit = loadedRegionSettings.TerrainLowerLimit;
842 currentRegionSettings.TerrainRaiseLimit = loadedRegionSettings.TerrainRaiseLimit;
843 currentRegionSettings.TerrainTexture1 = loadedRegionSettings.TerrainTexture1;
844 currentRegionSettings.TerrainTexture2 = loadedRegionSettings.TerrainTexture2;
845 currentRegionSettings.TerrainTexture3 = loadedRegionSettings.TerrainTexture3;
846 currentRegionSettings.TerrainTexture4 = loadedRegionSettings.TerrainTexture4;
847 currentRegionSettings.UseEstateSun = loadedRegionSettings.UseEstateSun;
848 currentRegionSettings.WaterHeight = loadedRegionSettings.WaterHeight;
849 currentRegionSettings.TelehubObject = loadedRegionSettings.TelehubObject;
850 currentRegionSettings.ClearSpawnPoints();
851 foreach (SpawnPoint sp in loadedRegionSettings.SpawnPoints())
852 currentRegionSettings.AddSpawnPoint(sp);
853  
854 currentRegionSettings.LoadedCreationDateTime = dearchivedScenes.LoadedCreationDateTime;
855 currentRegionSettings.LoadedCreationID = dearchivedScenes.GetOriginalRegionID(scene.RegionInfo.RegionID).ToString();
856  
857 currentRegionSettings.Save();
858  
859 scene.TriggerEstateSunUpdate();
860  
861 IEstateModule estateModule = scene.RequestModuleInterface<IEstateModule>();
862 if (estateModule != null)
863 estateModule.sendRegionHandshakeToAll();
864  
865 return true;
866 }
867  
868 /// <summary>
869 /// Load terrain data
870 /// </summary>
871 /// <param name="scene"></param>
872 /// <param name="terrainPath"></param>
873 /// <param name="data"></param>
874 /// <returns>
875 /// true if terrain was resolved successfully, false otherwise.
876 /// </returns>
877 private bool LoadTerrain(Scene scene, string terrainPath, byte[] data)
878 {
879 ITerrainModule terrainModule = scene.RequestModuleInterface<ITerrainModule>();
880  
881 MemoryStream ms = new MemoryStream(data);
882 if (m_displacement != Vector3.Zero || m_rotation != 0f)
883 {
884 Vector2 rotationCenter = new Vector2(m_rotationCenter.X, m_rotationCenter.Y);
885 terrainModule.LoadFromStream(terrainPath, m_displacement, m_rotation, rotationCenter, ms);
886 }
887 else
888 {
889 terrainModule.LoadFromStream(terrainPath, ms);
890 }
891 ms.Close();
892  
893 m_log.DebugFormat("[ARCHIVER]: Restored terrain {0}", terrainPath);
894  
895 return true;
896 }
897  
898 /// <summary>
899 /// Load oar control file
900 /// </summary>
901 /// <param name="path"></param>
902 /// <param name="data"></param>
903 /// <param name="dearchivedScenes"></param>
904 public DearchiveScenesInfo LoadControlFile(string path, byte[] data, DearchiveScenesInfo dearchivedScenes)
905 {
906 XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable());
907 XmlParserContext context = new XmlParserContext(null, nsmgr, null, XmlSpace.None);
908 XmlTextReader xtr = new XmlTextReader(Encoding.ASCII.GetString(data), XmlNodeType.Document, context);
909  
910 // Loaded metadata will be empty if no information exists in the archive
911 dearchivedScenes.LoadedCreationDateTime = 0;
912 dearchivedScenes.DefaultOriginalID = "";
913  
914 bool multiRegion = false;
915  
916 while (xtr.Read())
917 {
918 if (xtr.NodeType == XmlNodeType.Element)
919 {
920 if (xtr.Name.ToString() == "archive")
921 {
922 int majorVersion = int.Parse(xtr["major_version"]);
923 int minorVersion = int.Parse(xtr["minor_version"]);
924 string version = string.Format("{0}.{1}", majorVersion, minorVersion);
925  
926 if (majorVersion > MAX_MAJOR_VERSION)
927 {
928 throw new Exception(
929 string.Format(
930 "The OAR you are trying to load has major version number of {0} but this version of OpenSim can only load OARs with major version number {1} and below",
931 majorVersion, MAX_MAJOR_VERSION));
932 }
933  
934 m_log.InfoFormat("[ARCHIVER]: Loading OAR with version {0}", version);
935 }
936 if (xtr.Name.ToString() == "datetime")
937 {
938 int value;
939 if (Int32.TryParse(xtr.ReadElementContentAsString(), out value))
940 dearchivedScenes.LoadedCreationDateTime = value;
941 }
942 else if (xtr.Name.ToString() == "row")
943 {
944 multiRegion = true;
945 dearchivedScenes.StartRow();
946 }
947 else if (xtr.Name.ToString() == "region")
948 {
949 dearchivedScenes.StartRegion();
950 }
951 else if (xtr.Name.ToString() == "id")
952 {
953 string id = xtr.ReadElementContentAsString();
954 dearchivedScenes.DefaultOriginalID = id;
955 if (multiRegion)
956 dearchivedScenes.SetRegionOriginalID(id);
957 }
958 else if (xtr.Name.ToString() == "dir")
959 {
960 dearchivedScenes.SetRegionDirectory(xtr.ReadElementContentAsString());
961 }
962 }
963 }
964  
965 dearchivedScenes.MultiRegionFormat = multiRegion;
966 if (!multiRegion)
967 {
968 // Add the single scene
969 dearchivedScenes.StartRow();
970 dearchivedScenes.StartRegion();
971 dearchivedScenes.SetRegionOriginalID(dearchivedScenes.DefaultOriginalID);
972 dearchivedScenes.SetRegionDirectory("");
973 }
974  
975 ControlFileLoaded = true;
976  
977 return dearchivedScenes;
978 }
979 }
980 }