clockwerk-opensim-stable – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 vero 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 /// </value>
100 protected bool m_merge;
101  
102 /// <value>
103 /// Should we ignore any assets when reloading the archive?
104 /// </value>
105 protected bool m_skipAssets;
106  
107 /// <summary>
108 /// Used to cache lookups for valid uuids.
109 /// </summary>
110 private IDictionary<UUID, bool> m_validUserUuids = new Dictionary<UUID, bool>();
111  
112 private IUserManagement m_UserMan;
113 private IUserManagement UserManager
114 {
115 get
116 {
117 if (m_UserMan == null)
118 {
119 m_UserMan = m_rootScene.RequestModuleInterface<IUserManagement>();
120 }
121 return m_UserMan;
122 }
123 }
124  
125 /// <summary>
126 /// Used to cache lookups for valid groups.
127 /// </summary>
128 private IDictionary<UUID, bool> m_validGroupUuids = new Dictionary<UUID, bool>();
129  
130 private IGroupsModule m_groupsModule;
131  
132 private IAssetService m_assetService = null;
133  
134  
135 public ArchiveReadRequest(Scene scene, string loadPath, bool merge, bool skipAssets, Guid requestId)
136 {
137 m_rootScene = scene;
138  
139 m_loadPath = loadPath;
140 try
141 {
142 m_loadStream = new GZipStream(ArchiveHelpers.GetStream(loadPath), CompressionMode.Decompress);
143 }
144 catch (EntryPointNotFoundException e)
145 {
146 m_log.ErrorFormat(
147 "[ARCHIVER]: Mismatch between Mono and zlib1g library version when trying to create compression stream."
148 + "If you've manually installed Mono, have you appropriately updated zlib1g as well?");
149 m_log.Error(e);
150 }
151  
152 m_errorMessage = String.Empty;
153 m_merge = merge;
154 m_skipAssets = skipAssets;
155 m_requestId = requestId;
156  
157 // Zero can never be a valid user id
158 m_validUserUuids[UUID.Zero] = false;
159  
160 m_groupsModule = m_rootScene.RequestModuleInterface<IGroupsModule>();
161 m_assetService = m_rootScene.AssetService;
162 }
163  
164 public ArchiveReadRequest(Scene scene, Stream loadStream, bool merge, bool skipAssets, Guid requestId)
165 {
166 m_rootScene = scene;
167 m_loadPath = null;
168 m_loadStream = loadStream;
169 m_merge = merge;
170 m_skipAssets = skipAssets;
171 m_requestId = requestId;
172  
173 // Zero can never be a valid user id
174 m_validUserUuids[UUID.Zero] = false;
175  
176 m_groupsModule = m_rootScene.RequestModuleInterface<IGroupsModule>();
177 m_assetService = m_rootScene.AssetService;
178 }
179  
180 /// <summary>
181 /// Dearchive the region embodied in this request.
182 /// </summary>
183 public void DearchiveRegion()
184 {
185 int successfulAssetRestores = 0;
186 int failedAssetRestores = 0;
187  
188 DearchiveScenesInfo dearchivedScenes;
189  
190 // We dearchive all the scenes at once, because the files in the TAR archive might be mixed.
191 // Therefore, we have to keep track of the dearchive context of all the scenes.
192 Dictionary<UUID, DearchiveContext> sceneContexts = new Dictionary<UUID, DearchiveContext>();
193  
194 string fullPath = "NONE";
195 TarArchiveReader archive = null;
196 byte[] data;
197 TarArchiveReader.TarEntryType entryType;
198  
199 try
200 {
201 FindAndLoadControlFile(out archive, out dearchivedScenes);
202  
203 while ((data = archive.ReadEntry(out fullPath, out entryType)) != null)
204 {
205 //m_log.DebugFormat(
206 // "[ARCHIVER]: Successfully read {0} ({1} bytes)", filePath, data.Length);
207  
208 if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType)
209 continue;
210  
211  
212 // Find the scene that this file belongs to
213  
214 Scene scene;
215 string filePath;
216 if (!dearchivedScenes.GetRegionFromPath(fullPath, out scene, out filePath))
217 continue; // this file belongs to a region that we're not loading
218  
219 DearchiveContext sceneContext = null;
220 if (scene != null)
221 {
222 if (!sceneContexts.TryGetValue(scene.RegionInfo.RegionID, out sceneContext))
223 {
224 sceneContext = new DearchiveContext(scene);
225 sceneContexts.Add(scene.RegionInfo.RegionID, sceneContext);
226 }
227 }
228  
229  
230 // Process the file
231  
232 if (filePath.StartsWith(ArchiveConstants.OBJECTS_PATH))
233 {
234 sceneContext.SerialisedSceneObjects.Add(Encoding.UTF8.GetString(data));
235 }
236 else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH) && !m_skipAssets)
237 {
238 if (LoadAsset(filePath, data))
239 successfulAssetRestores++;
240 else
241 failedAssetRestores++;
242  
243 if ((successfulAssetRestores + failedAssetRestores) % 250 == 0)
244 m_log.Debug("[ARCHIVER]: Loaded " + successfulAssetRestores + " assets and failed to load " + failedAssetRestores + " assets...");
245 }
246 else if (!m_merge && filePath.StartsWith(ArchiveConstants.TERRAINS_PATH))
247 {
248 LoadTerrain(scene, filePath, data);
249 }
250 else if (!m_merge && filePath.StartsWith(ArchiveConstants.SETTINGS_PATH))
251 {
252 LoadRegionSettings(scene, filePath, data, dearchivedScenes);
253 }
254 else if (!m_merge && filePath.StartsWith(ArchiveConstants.LANDDATA_PATH))
255 {
256 sceneContext.SerialisedParcels.Add(Encoding.UTF8.GetString(data));
257 }
258 else if (filePath == ArchiveConstants.CONTROL_FILE_PATH)
259 {
260 // Ignore, because we already read the control file
261 }
262 }
263  
264 //m_log.Debug("[ARCHIVER]: Reached end of archive");
265 }
266 catch (Exception e)
267 {
268 m_log.Error(
269 String.Format("[ARCHIVER]: Aborting load with error in archive file {0} ", fullPath), e);
270 m_errorMessage += e.ToString();
271 m_rootScene.EventManager.TriggerOarFileLoaded(m_requestId, new List<UUID>(), m_errorMessage);
272 return;
273 }
274 finally
275 {
276 if (archive != null)
277 archive.Close();
278 }
279  
280 if (!m_skipAssets)
281 {
282 m_log.InfoFormat("[ARCHIVER]: Restored {0} assets", successfulAssetRestores);
283  
284 if (failedAssetRestores > 0)
285 {
286 m_log.ErrorFormat("[ARCHIVER]: Failed to load {0} assets", failedAssetRestores);
287 m_errorMessage += String.Format("Failed to load {0} assets", failedAssetRestores);
288 }
289 }
290  
291 foreach (DearchiveContext sceneContext in sceneContexts.Values)
292 {
293 m_log.InfoFormat("[ARCHIVER]: Loading region {0}", sceneContext.Scene.RegionInfo.RegionName);
294  
295 if (!m_merge)
296 {
297 m_log.Info("[ARCHIVER]: Clearing all existing scene objects");
298 sceneContext.Scene.DeleteAllSceneObjects();
299 }
300  
301 try
302 {
303 LoadParcels(sceneContext.Scene, sceneContext.SerialisedParcels);
304 LoadObjects(sceneContext.Scene, sceneContext.SerialisedSceneObjects, sceneContext.SceneObjects);
305  
306 // Inform any interested parties that the region has changed. We waited until now so that all
307 // of the region's objects will be loaded when we send this notification.
308 IEstateModule estateModule = sceneContext.Scene.RequestModuleInterface<IEstateModule>();
309 if (estateModule != null)
310 estateModule.TriggerRegionInfoChange();
311 }
312 catch (Exception e)
313 {
314 m_log.Error("[ARCHIVER]: Error loading parcels or objects ", e);
315 m_errorMessage += e.ToString();
316 m_rootScene.EventManager.TriggerOarFileLoaded(m_requestId, new List<UUID>(), m_errorMessage);
317 return;
318 }
319 }
320  
321 // Start the scripts. We delayed this because we want the OAR to finish loading ASAP, so
322 // that users can enter the scene. If we allow the scripts to start in the loop above
323 // then they significantly increase the time until the OAR finishes loading.
324 Util.FireAndForget(delegate(object o)
325 {
326 Thread.Sleep(15000);
327 m_log.Info("[ARCHIVER]: Starting scripts in scene objects");
328  
329 foreach (DearchiveContext sceneContext in sceneContexts.Values)
330 {
331 foreach (SceneObjectGroup sceneObject in sceneContext.SceneObjects)
332 {
333 sceneObject.CreateScriptInstances(0, false, sceneContext.Scene.DefaultScriptEngine, 0); // StateSource.RegionStart
334 sceneObject.ResumeScripts();
335 }
336  
337 sceneContext.SceneObjects.Clear();
338 }
339 });
340  
341 m_log.InfoFormat("[ARCHIVER]: Successfully loaded archive");
342  
343 m_rootScene.EventManager.TriggerOarFileLoaded(m_requestId, dearchivedScenes.GetLoadedScenes(), m_errorMessage);
344 }
345  
346 /// <summary>
347 /// Searches through the files in the archive for the control file, and reads it.
348 /// We must read the control file first, in order to know which regions are available.
349 /// </summary>
350 /// <remarks>
351 /// In most cases the control file *is* first, since that's how we create archives. However,
352 /// it's possible that someone rewrote the archive externally so we can't rely on this fact.
353 /// </remarks>
354 /// <param name="archive"></param>
355 /// <param name="dearchivedScenes"></param>
356 private void FindAndLoadControlFile(out TarArchiveReader archive, out DearchiveScenesInfo dearchivedScenes)
357 {
358 archive = new TarArchiveReader(m_loadStream);
359 dearchivedScenes = new DearchiveScenesInfo();
360  
361 string filePath;
362 byte[] data;
363 TarArchiveReader.TarEntryType entryType;
364 bool firstFile = true;
365  
366 while ((data = archive.ReadEntry(out filePath, out entryType)) != null)
367 {
368 if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType)
369 continue;
370  
371 if (filePath == ArchiveConstants.CONTROL_FILE_PATH)
372 {
373 LoadControlFile(filePath, data, dearchivedScenes);
374  
375 // Find which scenes are available in the simulator
376 ArchiveScenesGroup simulatorScenes = new ArchiveScenesGroup();
377 SceneManager.Instance.ForEachScene(delegate(Scene scene2)
378 {
379 simulatorScenes.AddScene(scene2);
380 });
381 simulatorScenes.CalcSceneLocations();
382 dearchivedScenes.SetSimulatorScenes(m_rootScene, simulatorScenes);
383  
384 // If the control file wasn't the first file then reset the read pointer
385 if (!firstFile)
386 {
387 m_log.Warn("Control file wasn't the first file in the archive");
388 if (m_loadStream.CanSeek)
389 {
390 m_loadStream.Seek(0, SeekOrigin.Begin);
391 }
392 else if (m_loadPath != null)
393 {
394 archive.Close();
395 archive = null;
396 m_loadStream.Close();
397 m_loadStream = null;
398 m_loadStream = new GZipStream(ArchiveHelpers.GetStream(m_loadPath), CompressionMode.Decompress);
399 archive = new TarArchiveReader(m_loadStream);
400 }
401 else
402 {
403 // There isn't currently a scenario where this happens, but it's best to add a check just in case
404 throw new Exception("Error reading archive: control file wasn't the first file, and the input stream doesn't allow seeking");
405 }
406 }
407  
408 return;
409 }
410  
411 firstFile = false;
412 }
413  
414 throw new Exception("Control file not found");
415 }
416  
417 /// <summary>
418 /// Load serialized scene objects.
419 /// </summary>
420 protected void LoadObjects(Scene scene, List<string> serialisedSceneObjects, List<SceneObjectGroup> sceneObjects)
421 {
422 // Reload serialized prims
423 m_log.InfoFormat("[ARCHIVER]: Loading {0} scene objects. Please wait.", serialisedSceneObjects.Count);
424  
425 UUID oldTelehubUUID = scene.RegionInfo.RegionSettings.TelehubObject;
426  
427 IRegionSerialiserModule serialiser = scene.RequestModuleInterface<IRegionSerialiserModule>();
428 int sceneObjectsLoadedCount = 0;
429  
430 foreach (string serialisedSceneObject in serialisedSceneObjects)
431 {
432 /*
433 m_log.DebugFormat("[ARCHIVER]: Loading xml with raw size {0}", serialisedSceneObject.Length);
434  
435 // Really large xml files (multi megabyte) appear to cause
436 // memory problems
437 // when loading the xml. But don't enable this check yet
438  
439 if (serialisedSceneObject.Length > 5000000)
440 {
441 m_log.Error("[ARCHIVER]: Ignoring xml since size > 5000000);");
442 continue;
443 }
444 */
445  
446 SceneObjectGroup sceneObject = serialiser.DeserializeGroupFromXml2(serialisedSceneObject);
447  
448 bool isTelehub = (sceneObject.UUID == oldTelehubUUID) && (oldTelehubUUID != UUID.Zero);
449  
450 // For now, give all incoming scene objects new uuids. This will allow scenes to be cloned
451 // on the same region server and multiple examples a single object archive to be imported
452 // to the same scene (when this is possible).
453 sceneObject.ResetIDs();
454  
455 if (isTelehub)
456 {
457 // Change the Telehub Object to the new UUID
458 scene.RegionInfo.RegionSettings.TelehubObject = sceneObject.UUID;
459 scene.RegionInfo.RegionSettings.Save();
460 oldTelehubUUID = UUID.Zero;
461 }
462  
463 // Try to retain the original creator/owner/lastowner if their uuid is present on this grid
464 // or creator data is present. Otherwise, use the estate owner instead.
465 foreach (SceneObjectPart part in sceneObject.Parts)
466 {
467 if (part.CreatorData == null || part.CreatorData == string.Empty)
468 {
469 if (!ResolveUserUuid(scene, part.CreatorID))
470 part.CreatorID = scene.RegionInfo.EstateSettings.EstateOwner;
471 }
472 if (UserManager != null)
473 UserManager.AddUser(part.CreatorID, part.CreatorData);
474  
475 if (!ResolveUserUuid(scene, part.OwnerID))
476 part.OwnerID = scene.RegionInfo.EstateSettings.EstateOwner;
477  
478 if (!ResolveUserUuid(scene, part.LastOwnerID))
479 part.LastOwnerID = scene.RegionInfo.EstateSettings.EstateOwner;
480  
481 if (!ResolveGroupUuid(part.GroupID))
482 part.GroupID = UUID.Zero;
483  
484 // And zap any troublesome sit target information
485 // part.SitTargetOrientation = new Quaternion(0, 0, 0, 1);
486 // part.SitTargetPosition = new Vector3(0, 0, 0);
487  
488 // Fix ownership/creator of inventory items
489 // Not doing so results in inventory items
490 // being no copy/no mod for everyone
491 lock (part.TaskInventory)
492 {
493 TaskInventoryDictionary inv = part.TaskInventory;
494 foreach (KeyValuePair<UUID, TaskInventoryItem> kvp in inv)
495 {
496 if (!ResolveUserUuid(scene, kvp.Value.OwnerID))
497 {
498 kvp.Value.OwnerID = scene.RegionInfo.EstateSettings.EstateOwner;
499 }
500  
501 if (kvp.Value.CreatorData == null || kvp.Value.CreatorData == string.Empty)
502 {
503 if (!ResolveUserUuid(scene, kvp.Value.CreatorID))
504 kvp.Value.CreatorID = scene.RegionInfo.EstateSettings.EstateOwner;
505 }
506  
507 if (UserManager != null)
508 UserManager.AddUser(kvp.Value.CreatorID, kvp.Value.CreatorData);
509  
510 if (!ResolveGroupUuid(kvp.Value.GroupID))
511 kvp.Value.GroupID = UUID.Zero;
512 }
513 }
514 }
515  
516 if (scene.AddRestoredSceneObject(sceneObject, true, false))
517 {
518 sceneObjectsLoadedCount++;
519 sceneObject.CreateScriptInstances(0, false, scene.DefaultScriptEngine, 0);
520 sceneObject.ResumeScripts();
521 }
522 }
523  
524 m_log.InfoFormat("[ARCHIVER]: Restored {0} scene objects to the scene", sceneObjectsLoadedCount);
525  
526 int ignoredObjects = serialisedSceneObjects.Count - sceneObjectsLoadedCount;
527  
528 if (ignoredObjects > 0)
529 m_log.WarnFormat("[ARCHIVER]: Ignored {0} scene objects that already existed in the scene", ignoredObjects);
530  
531 if (oldTelehubUUID != UUID.Zero)
532 {
533 m_log.WarnFormat("Telehub object not found: {0}", oldTelehubUUID);
534 scene.RegionInfo.RegionSettings.TelehubObject = UUID.Zero;
535 scene.RegionInfo.RegionSettings.ClearSpawnPoints();
536 }
537 }
538  
539 /// <summary>
540 /// Load serialized parcels.
541 /// </summary>
542 /// <param name="scene"></param>
543 /// <param name="serialisedParcels"></param>
544 protected void LoadParcels(Scene scene, List<string> serialisedParcels)
545 {
546 // Reload serialized parcels
547 m_log.InfoFormat("[ARCHIVER]: Loading {0} parcels. Please wait.", serialisedParcels.Count);
548 List<LandData> landData = new List<LandData>();
549 foreach (string serialisedParcel in serialisedParcels)
550 {
551 LandData parcel = LandDataSerializer.Deserialize(serialisedParcel);
552  
553 // Validate User and Group UUID's
554  
555 if (parcel.IsGroupOwned)
556 {
557 if (!ResolveGroupUuid(parcel.GroupID))
558 {
559 parcel.OwnerID = m_rootScene.RegionInfo.EstateSettings.EstateOwner;
560 parcel.GroupID = UUID.Zero;
561 parcel.IsGroupOwned = false;
562 }
563 }
564 else
565 {
566 if (!ResolveUserUuid(scene, parcel.OwnerID))
567 parcel.OwnerID = m_rootScene.RegionInfo.EstateSettings.EstateOwner;
568  
569 if (!ResolveGroupUuid(parcel.GroupID))
570 parcel.GroupID = UUID.Zero;
571 }
572  
573 List<LandAccessEntry> accessList = new List<LandAccessEntry>();
574 foreach (LandAccessEntry entry in parcel.ParcelAccessList)
575 {
576 if (ResolveUserUuid(scene, entry.AgentID))
577 accessList.Add(entry);
578 // else, drop this access rule
579 }
580 parcel.ParcelAccessList = accessList;
581  
582 // m_log.DebugFormat(
583 // "[ARCHIVER]: Adding parcel {0}, local id {1}, owner {2}, group {3}, isGroupOwned {4}, area {5}",
584 // parcel.Name, parcel.LocalID, parcel.OwnerID, parcel.GroupID, parcel.IsGroupOwned, parcel.Area);
585  
586 landData.Add(parcel);
587 }
588  
589 if (!m_merge)
590 {
591 bool setupDefaultParcel = (landData.Count == 0);
592 scene.LandChannel.Clear(setupDefaultParcel);
593 }
594  
595 scene.EventManager.TriggerIncomingLandDataFromStorage(landData);
596 m_log.InfoFormat("[ARCHIVER]: Restored {0} parcels.", landData.Count);
597 }
598  
599 /// <summary>
600 /// Look up the given user id to check whether it's one that is valid for this grid.
601 /// </summary>
602 /// <param name="scene"></param>
603 /// <param name="uuid"></param>
604 /// <returns></returns>
605 private bool ResolveUserUuid(Scene scene, UUID uuid)
606 {
607 lock (m_validUserUuids)
608 {
609 if (!m_validUserUuids.ContainsKey(uuid))
610 {
611 // Note: we call GetUserAccount() inside the lock because this UserID is likely
612 // to occur many times, and we only want to query the users service once.
613 UserAccount account = scene.UserAccountService.GetUserAccount(scene.RegionInfo.ScopeID, uuid);
614 m_validUserUuids.Add(uuid, account != null);
615 }
616  
617 return m_validUserUuids[uuid];
618 }
619 }
620  
621 /// <summary>
622 /// Look up the given group id to check whether it's one that is valid for this grid.
623 /// </summary>
624 /// <param name="uuid"></param>
625 /// <returns></returns>
626 private bool ResolveGroupUuid(UUID uuid)
627 {
628 if (uuid == UUID.Zero)
629 return true; // this means the object has no group
630  
631 lock (m_validGroupUuids)
632 {
633 if (!m_validGroupUuids.ContainsKey(uuid))
634 {
635 bool exists;
636 if (m_groupsModule == null)
637 {
638 exists = false;
639 }
640 else
641 {
642 // Note: we call GetGroupRecord() inside the lock because this GroupID is likely
643 // to occur many times, and we only want to query the groups service once.
644 exists = (m_groupsModule.GetGroupRecord(uuid) != null);
645 }
646 m_validGroupUuids.Add(uuid, exists);
647 }
648  
649 return m_validGroupUuids[uuid];
650 }
651 }
652  
653 /// Load an asset
654 /// </summary>
655 /// <param name="assetFilename"></param>
656 /// <param name="data"></param>
657 /// <returns>true if asset was successfully loaded, false otherwise</returns>
658 private bool LoadAsset(string assetPath, byte[] data)
659 {
660 // Right now we're nastily obtaining the UUID from the filename
661 string filename = assetPath.Remove(0, ArchiveConstants.ASSETS_PATH.Length);
662 int i = filename.LastIndexOf(ArchiveConstants.ASSET_EXTENSION_SEPARATOR);
663  
664 if (i == -1)
665 {
666 m_log.ErrorFormat(
667 "[ARCHIVER]: Could not find extension information in asset path {0} since it's missing the separator {1}. Skipping",
668 assetPath, ArchiveConstants.ASSET_EXTENSION_SEPARATOR);
669  
670 return false;
671 }
672  
673 string extension = filename.Substring(i);
674 string uuid = filename.Remove(filename.Length - extension.Length);
675  
676 if (m_assetService.GetMetadata(uuid) != null)
677 {
678 // m_log.DebugFormat("[ARCHIVER]: found existing asset {0}",uuid);
679 return true;
680 }
681  
682 if (ArchiveConstants.EXTENSION_TO_ASSET_TYPE.ContainsKey(extension))
683 {
684 sbyte assetType = ArchiveConstants.EXTENSION_TO_ASSET_TYPE[extension];
685  
686 if (assetType == (sbyte)AssetType.Unknown)
687 m_log.WarnFormat("[ARCHIVER]: Importing {0} byte asset {1} with unknown type", data.Length, uuid);
688  
689 //m_log.DebugFormat("[ARCHIVER]: Importing asset {0}, type {1}", uuid, assetType);
690  
691 AssetBase asset = new AssetBase(new UUID(uuid), String.Empty, assetType, UUID.Zero.ToString());
692 asset.Data = data;
693  
694 // We're relying on the asset service to do the sensible thing and not store the asset if it already
695 // exists.
696 m_assetService.Store(asset);
697  
698 /**
699 * Create layers on decode for image assets. This is likely to significantly increase the time to load archives so
700 * it might be best done when dearchive takes place on a separate thread
701 if (asset.Type=AssetType.Texture)
702 {
703 IJ2KDecoder cacheLayerDecode = scene.RequestModuleInterface<IJ2KDecoder>();
704 if (cacheLayerDecode != null)
705 cacheLayerDecode.syncdecode(asset.FullID, asset.Data);
706 }
707 */
708  
709 return true;
710 }
711 else
712 {
713 m_log.ErrorFormat(
714 "[ARCHIVER]: Tried to dearchive data with path {0} with an unknown type extension {1}",
715 assetPath, extension);
716  
717 return false;
718 }
719 }
720  
721 /// <summary>
722 /// Load region settings data
723 /// </summary>
724 /// <param name="scene"></param>
725 /// <param name="settingsPath"></param>
726 /// <param name="data"></param>
727 /// <param name="dearchivedScenes"></param>
728 /// <returns>
729 /// true if settings were loaded successfully, false otherwise
730 /// </returns>
731 private bool LoadRegionSettings(Scene scene, string settingsPath, byte[] data, DearchiveScenesInfo dearchivedScenes)
732 {
733 RegionSettings loadedRegionSettings;
734  
735 try
736 {
737 loadedRegionSettings = RegionSettingsSerializer.Deserialize(data);
738 }
739 catch (Exception e)
740 {
741 m_log.ErrorFormat(
742 "[ARCHIVER]: Could not parse region settings file {0}. Ignoring. Exception was {1}",
743 settingsPath, e);
744 return false;
745 }
746  
747 RegionSettings currentRegionSettings = scene.RegionInfo.RegionSettings;
748  
749 currentRegionSettings.AgentLimit = loadedRegionSettings.AgentLimit;
750 currentRegionSettings.AllowDamage = loadedRegionSettings.AllowDamage;
751 currentRegionSettings.AllowLandJoinDivide = loadedRegionSettings.AllowLandJoinDivide;
752 currentRegionSettings.AllowLandResell = loadedRegionSettings.AllowLandResell;
753 currentRegionSettings.BlockFly = loadedRegionSettings.BlockFly;
754 currentRegionSettings.BlockShowInSearch = loadedRegionSettings.BlockShowInSearch;
755 currentRegionSettings.BlockTerraform = loadedRegionSettings.BlockTerraform;
756 currentRegionSettings.DisableCollisions = loadedRegionSettings.DisableCollisions;
757 currentRegionSettings.DisablePhysics = loadedRegionSettings.DisablePhysics;
758 currentRegionSettings.DisableScripts = loadedRegionSettings.DisableScripts;
759 currentRegionSettings.Elevation1NE = loadedRegionSettings.Elevation1NE;
760 currentRegionSettings.Elevation1NW = loadedRegionSettings.Elevation1NW;
761 currentRegionSettings.Elevation1SE = loadedRegionSettings.Elevation1SE;
762 currentRegionSettings.Elevation1SW = loadedRegionSettings.Elevation1SW;
763 currentRegionSettings.Elevation2NE = loadedRegionSettings.Elevation2NE;
764 currentRegionSettings.Elevation2NW = loadedRegionSettings.Elevation2NW;
765 currentRegionSettings.Elevation2SE = loadedRegionSettings.Elevation2SE;
766 currentRegionSettings.Elevation2SW = loadedRegionSettings.Elevation2SW;
767 currentRegionSettings.FixedSun = loadedRegionSettings.FixedSun;
768 currentRegionSettings.SunPosition = loadedRegionSettings.SunPosition;
769 currentRegionSettings.ObjectBonus = loadedRegionSettings.ObjectBonus;
770 currentRegionSettings.RestrictPushing = loadedRegionSettings.RestrictPushing;
771 currentRegionSettings.TerrainLowerLimit = loadedRegionSettings.TerrainLowerLimit;
772 currentRegionSettings.TerrainRaiseLimit = loadedRegionSettings.TerrainRaiseLimit;
773 currentRegionSettings.TerrainTexture1 = loadedRegionSettings.TerrainTexture1;
774 currentRegionSettings.TerrainTexture2 = loadedRegionSettings.TerrainTexture2;
775 currentRegionSettings.TerrainTexture3 = loadedRegionSettings.TerrainTexture3;
776 currentRegionSettings.TerrainTexture4 = loadedRegionSettings.TerrainTexture4;
777 currentRegionSettings.UseEstateSun = loadedRegionSettings.UseEstateSun;
778 currentRegionSettings.WaterHeight = loadedRegionSettings.WaterHeight;
779 currentRegionSettings.TelehubObject = loadedRegionSettings.TelehubObject;
780 currentRegionSettings.ClearSpawnPoints();
781 foreach (SpawnPoint sp in loadedRegionSettings.SpawnPoints())
782 currentRegionSettings.AddSpawnPoint(sp);
783  
784 currentRegionSettings.LoadedCreationDateTime = dearchivedScenes.LoadedCreationDateTime;
785 currentRegionSettings.LoadedCreationID = dearchivedScenes.GetOriginalRegionID(scene.RegionInfo.RegionID).ToString();
786  
787 currentRegionSettings.Save();
788  
789 scene.TriggerEstateSunUpdate();
790  
791 IEstateModule estateModule = scene.RequestModuleInterface<IEstateModule>();
792 if (estateModule != null)
793 estateModule.sendRegionHandshakeToAll();
794  
795 return true;
796 }
797  
798 /// <summary>
799 /// Load terrain data
800 /// </summary>
801 /// <param name="scene"></param>
802 /// <param name="terrainPath"></param>
803 /// <param name="data"></param>
804 /// <returns>
805 /// true if terrain was resolved successfully, false otherwise.
806 /// </returns>
807 private bool LoadTerrain(Scene scene, string terrainPath, byte[] data)
808 {
809 ITerrainModule terrainModule = scene.RequestModuleInterface<ITerrainModule>();
810  
811 MemoryStream ms = new MemoryStream(data);
812 terrainModule.LoadFromStream(terrainPath, ms);
813 ms.Close();
814  
815 m_log.DebugFormat("[ARCHIVER]: Restored terrain {0}", terrainPath);
816  
817 return true;
818 }
819  
820 /// <summary>
821 /// Load oar control file
822 /// </summary>
823 /// <param name="path"></param>
824 /// <param name="data"></param>
825 /// <param name="dearchivedScenes"></param>
826 public DearchiveScenesInfo LoadControlFile(string path, byte[] data, DearchiveScenesInfo dearchivedScenes)
827 {
828 XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable());
829 XmlParserContext context = new XmlParserContext(null, nsmgr, null, XmlSpace.None);
830 XmlTextReader xtr = new XmlTextReader(Encoding.ASCII.GetString(data), XmlNodeType.Document, context);
831  
832 // Loaded metadata will be empty if no information exists in the archive
833 dearchivedScenes.LoadedCreationDateTime = 0;
834 dearchivedScenes.DefaultOriginalID = "";
835  
836 bool multiRegion = false;
837  
838 while (xtr.Read())
839 {
840 if (xtr.NodeType == XmlNodeType.Element)
841 {
842 if (xtr.Name.ToString() == "archive")
843 {
844 int majorVersion = int.Parse(xtr["major_version"]);
845 int minorVersion = int.Parse(xtr["minor_version"]);
846 string version = string.Format("{0}.{1}", majorVersion, minorVersion);
847  
848 if (majorVersion > MAX_MAJOR_VERSION)
849 {
850 throw new Exception(
851 string.Format(
852 "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",
853 majorVersion, MAX_MAJOR_VERSION));
854 }
855  
856 m_log.InfoFormat("[ARCHIVER]: Loading OAR with version {0}", version);
857 }
858 if (xtr.Name.ToString() == "datetime")
859 {
860 int value;
861 if (Int32.TryParse(xtr.ReadElementContentAsString(), out value))
862 dearchivedScenes.LoadedCreationDateTime = value;
863 }
864 else if (xtr.Name.ToString() == "row")
865 {
866 multiRegion = true;
867 dearchivedScenes.StartRow();
868 }
869 else if (xtr.Name.ToString() == "region")
870 {
871 dearchivedScenes.StartRegion();
872 }
873 else if (xtr.Name.ToString() == "id")
874 {
875 string id = xtr.ReadElementContentAsString();
876 dearchivedScenes.DefaultOriginalID = id;
877 if (multiRegion)
878 dearchivedScenes.SetRegionOriginalID(id);
879 }
880 else if (xtr.Name.ToString() == "dir")
881 {
882 dearchivedScenes.SetRegionDirectory(xtr.ReadElementContentAsString());
883 }
884 }
885 }
886  
887 dearchivedScenes.MultiRegionFormat = multiRegion;
888 if (!multiRegion)
889 {
890 // Add the single scene
891 dearchivedScenes.StartRow();
892 dearchivedScenes.StartRegion();
893 dearchivedScenes.SetRegionOriginalID(dearchivedScenes.DefaultOriginalID);
894 dearchivedScenes.SetRegionDirectory("");
895 }
896  
897 ControlFileLoaded = true;
898  
899 return dearchivedScenes;
900 }
901 }
902 }