ArchiveReadRequest.cs 44 KB

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