PageRenderTime 45ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/Aurora/Modules/World/Startup/Backup.cs

https://bitbucket.org/VirtualReality/async-sim-testing
C# | 931 lines | 722 code | 107 blank | 102 comment | 121 complexity | f9a54cf32638815a14fa8c8ccecf5b09 MD5 | raw file
  1. /*
  2. * Copyright (c) Contributors, http://aurora-sim.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 Aurora-Sim 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 Aurora.Framework;
  28. using Aurora.Framework.ConsoleFramework;
  29. using Aurora.Framework.Modules;
  30. using Aurora.Framework.PresenceInfo;
  31. using Aurora.Framework.SceneInfo;
  32. using Aurora.Framework.SceneInfo.Entities;
  33. using Aurora.Framework.Serialization;
  34. using Aurora.Framework.Services;
  35. using Aurora.Framework.Services.ClassHelpers.Assets;
  36. using Aurora.Framework.Utilities;
  37. using Nini.Config;
  38. using OpenMetaverse;
  39. using OpenMetaverse.StructuredData;
  40. using System;
  41. using System.Collections.Generic;
  42. using System.IO;
  43. using System.Linq;
  44. using System.Text;
  45. using System.Threading;
  46. namespace Aurora.Modules.Startup
  47. {
  48. public class Backup : ISharedRegionStartupModule
  49. {
  50. #region Declares
  51. protected ISceneManager m_manager;
  52. protected Dictionary<IScene, InternalSceneBackup> m_backup = new Dictionary<IScene, InternalSceneBackup>();
  53. #endregion
  54. #region ISharedRegionStartupModule Members
  55. public void Initialise(IScene scene, IConfigSource source, ISimulationBase openSimBase)
  56. {
  57. if (MainConsole.Instance != null && m_backup.Count == 0) //Only add them once
  58. {
  59. MainConsole.Instance.Commands.AddCommand("edit scale", "edit scale <name> <X> <Y> <Z>",
  60. "Change the scale of a named prim", EditScale);
  61. MainConsole.Instance.Commands.AddCommand("backup", "backup",
  62. "Persist objects to the database now, if [all], will force the persistence of all prims",
  63. RunCommand);
  64. MainConsole.Instance.Commands.AddCommand("disable backup", "disable backup",
  65. "Disables persistance until reenabled", DisableBackup);
  66. MainConsole.Instance.Commands.AddCommand("enable backup", "disable backup",
  67. "Enables persistance after 'disable persistance' has been run",
  68. EnableBackup);
  69. }
  70. //Set up the backup for the scene
  71. m_backup[scene] = new InternalSceneBackup(scene);
  72. }
  73. public void PostInitialise(IScene scene, IConfigSource source, ISimulationBase openSimBase)
  74. {
  75. }
  76. public void FinishStartup(IScene scene, IConfigSource source, ISimulationBase openSimBase)
  77. {
  78. }
  79. public void PostFinishStartup(IScene scene, IConfigSource source, ISimulationBase openSimBase)
  80. {
  81. m_manager = scene.RequestModuleInterface<ISceneManager>();
  82. m_backup[scene].FinishStartup();
  83. }
  84. public void StartupComplete()
  85. {
  86. EnableBackup(null);
  87. }
  88. public void Close(IScene scene)
  89. {
  90. m_backup.Remove(scene);
  91. }
  92. public void DeleteRegion(IScene scene)
  93. {
  94. }
  95. #endregion
  96. #region Console commands
  97. /// <summary>
  98. /// Runs commands issued by the server console from the operator
  99. /// </summary>
  100. /// <param name="cmdparams">Additional arguments passed to the command</param>
  101. public void RunCommand(string[] cmdparams)
  102. {
  103. m_manager.Scene.AuroraEventManager.FireGenericEventHandler("Backup", null);
  104. }
  105. public void EditScale(string[] cmdparams)
  106. {
  107. m_manager.Scene.ForEachSceneEntity(delegate(ISceneEntity entity)
  108. {
  109. foreach (ISceneChildEntity child in entity.ChildrenEntities())
  110. {
  111. if (child.Name == cmdparams[2])
  112. {
  113. child.Resize(
  114. new Vector3(Convert.ToSingle(cmdparams[3]),
  115. Convert.ToSingle(cmdparams[4]),
  116. Convert.ToSingle(cmdparams[5])));
  117. MainConsole.Instance.InfoFormat(
  118. "Edited scale of Primitive: {0}", child.Name);
  119. }
  120. }
  121. });
  122. }
  123. public void DisableBackup(string[] cmdparams)
  124. {
  125. m_manager.Scene.SimulationDataService.SaveBackups = false;
  126. MainConsole.Instance.Warn("Disabled backup");
  127. }
  128. public void EnableBackup(string[] cmdparams)
  129. {
  130. m_manager.Scene.SimulationDataService.SaveBackups = true;
  131. if (cmdparams != null) //so that it doesn't show on startup
  132. MainConsole.Instance.Warn("Enabled backup");
  133. }
  134. #endregion
  135. #region Per region backup class
  136. protected class InternalSceneBackup : IBackupModule, IAuroraBackupModule
  137. {
  138. #region Declares
  139. protected IScene m_scene;
  140. protected bool m_LoadingPrims;
  141. #endregion
  142. #region Constructor
  143. public InternalSceneBackup(IScene scene)
  144. {
  145. m_scene = scene;
  146. m_scene.StackModuleInterface<IAuroraBackupModule>(this);
  147. m_scene.RegisterModuleInterface<IBackupModule>(this);
  148. if (MainConsole.Instance != null)
  149. {
  150. MainConsole.Instance.Commands.AddCommand("delete object owner",
  151. "delete object owner <UUID>",
  152. "Delete object by owner", HandleDeleteObject);
  153. MainConsole.Instance.Commands.AddCommand("delete object creator",
  154. "delete object creator <UUID>",
  155. "Delete object by creator", HandleDeleteObject);
  156. MainConsole.Instance.Commands.AddCommand("delete object uuid",
  157. "delete object uuid <UUID>",
  158. "Delete object by uuid", HandleDeleteObject);
  159. MainConsole.Instance.Commands.AddCommand("delete object name",
  160. "delete object name <name>",
  161. "Delete object by name", HandleDeleteObject);
  162. }
  163. }
  164. #endregion
  165. #region Console Commands
  166. private void HandleDeleteObject(string[] cmd)
  167. {
  168. if (cmd.Length < 4)
  169. return;
  170. string mode = cmd[2];
  171. string o = cmd[3];
  172. List<ISceneEntity> deletes = new List<ISceneEntity>();
  173. UUID match;
  174. switch (mode)
  175. {
  176. case "owner":
  177. if (!UUID.TryParse(o, out match))
  178. return;
  179. m_scene.ForEachSceneEntity(delegate(ISceneEntity g)
  180. {
  181. if (g.OwnerID == match && !g.IsAttachment)
  182. deletes.Add(g);
  183. });
  184. break;
  185. case "creator":
  186. if (!UUID.TryParse(o, out match))
  187. return;
  188. m_scene.ForEachSceneEntity(delegate(ISceneEntity g)
  189. {
  190. if (g.RootChild.CreatorID == match && !g.IsAttachment)
  191. deletes.Add(g);
  192. });
  193. break;
  194. case "uuid":
  195. if (!UUID.TryParse(o, out match))
  196. return;
  197. m_scene.ForEachSceneEntity(delegate(ISceneEntity g)
  198. {
  199. if (g.UUID == match && !g.IsAttachment)
  200. deletes.Add(g);
  201. });
  202. break;
  203. case "name":
  204. m_scene.ForEachSceneEntity(delegate(ISceneEntity g)
  205. {
  206. if (g.RootChild.Name == o && !g.IsAttachment)
  207. deletes.Add(g);
  208. });
  209. break;
  210. }
  211. MainConsole.Instance.Warn("Deleting " + deletes.Count + " objects.");
  212. DeleteSceneObjects(deletes.ToArray(), true, true);
  213. }
  214. #endregion
  215. #region Scene events
  216. /// <summary>
  217. /// Loads the World's objects
  218. /// </summary>
  219. public void LoadPrimsFromStorage()
  220. {
  221. LoadingPrims = true;
  222. MainConsole.Instance.Info("[BackupModule]: Loading objects for " + m_scene.RegionInfo.RegionName +
  223. " from " + m_scene.SimulationDataService.Name);
  224. List<ISceneEntity> PrimsFromDB = m_scene.SimulationDataService.LoadObjects();
  225. foreach (ISceneEntity group in PrimsFromDB)
  226. {
  227. try
  228. {
  229. if (group == null)
  230. {
  231. MainConsole.Instance.Warn("[BackupModule]: Null object while loading objects, ignoring.");
  232. continue;
  233. }
  234. if (group.RootChild.Shape == null)
  235. {
  236. MainConsole.Instance.Warn("[BackupModule]: Broken object (" + group.Name +
  237. ") found while loading objects, removing it from the database.");
  238. //WTF went wrong here? Remove by passing it by on loading
  239. continue;
  240. }
  241. if (group.IsAttachment || (group.RootChild.Shape.State != 0 &&
  242. (group.RootChild.Shape.PCode == (byte) PCode.None ||
  243. group.RootChild.Shape.PCode == (byte) PCode.Prim ||
  244. group.RootChild.Shape.PCode == (byte) PCode.Avatar)))
  245. {
  246. MainConsole.Instance.Warn("[BackupModule]: Broken state for object " + group.Name +
  247. " while loading objects, removing it from the database.");
  248. //WTF went wrong here? Remove by passing it by on loading
  249. continue;
  250. }
  251. if (group.AbsolutePosition.X > m_scene.RegionInfo.RegionSizeX + 10 ||
  252. group.AbsolutePosition.X < -10 ||
  253. group.AbsolutePosition.Y > m_scene.RegionInfo.RegionSizeY + 10 ||
  254. group.AbsolutePosition.Y < -10)
  255. {
  256. MainConsole.Instance.Warn("[BackupModule]: Object outside the region (" + group.Name + ", " +
  257. group.AbsolutePosition +
  258. ") found while loading objects, removing it from the database.");
  259. //WTF went wrong here? Remove by passing it by on loading
  260. continue;
  261. }
  262. m_scene.SceneGraph.CheckAllocationOfLocalIds(group);
  263. group.Scene = m_scene;
  264. group.FinishedSerializingGenericProperties();
  265. if (group.RootChild == null)
  266. {
  267. MainConsole.Instance.ErrorFormat(
  268. "[BackupModule] Found a SceneObjectGroup with m_rootPart == null and {0} children",
  269. group.ChildrenEntities().Count);
  270. continue;
  271. }
  272. m_scene.SceneGraph.RestorePrimToScene(group, false);
  273. }
  274. catch (Exception ex)
  275. {
  276. MainConsole.Instance.WarnFormat(
  277. "[BackupModule]: Exception attempting to load object from the database, {0}, continuing...",
  278. ex.ToString());
  279. }
  280. }
  281. LoadingPrims = false;
  282. MainConsole.Instance.Info("[BackupModule]: Loaded " + PrimsFromDB.Count.ToString() + " object(s) in " +
  283. m_scene.RegionInfo.RegionName);
  284. PrimsFromDB.Clear();
  285. }
  286. /// <summary>
  287. /// Loads all Parcel data from the datastore for region identified by regionID
  288. /// </summary>
  289. public void LoadAllLandObjectsFromStorage()
  290. {
  291. MainConsole.Instance.Debug("[BackupModule]: Loading Land Objects from database... ");
  292. m_scene.EventManager.TriggerIncomingLandDataFromStorage(
  293. m_scene.SimulationDataService.LoadLandObjects(), Vector2.Zero);
  294. }
  295. public void FinishStartup()
  296. {
  297. //Load the prims from the database now that we are done loading
  298. LoadPrimsFromStorage();
  299. //Then load the land objects
  300. LoadAllLandObjectsFromStorage();
  301. //Load the prims from the database now that we are done loading
  302. CreateScriptInstances();
  303. //Now destroy the local caches as we're all loaded
  304. m_scene.SimulationDataService.CacheDispose();
  305. }
  306. /// <summary>
  307. /// Start all the scripts in the scene which should be started.
  308. /// </summary>
  309. public void CreateScriptInstances()
  310. {
  311. MainConsole.Instance.Info("[BackupModule]: Starting scripts in " + m_scene.RegionInfo.RegionName);
  312. //Set loading prims here to block backup
  313. LoadingPrims = true;
  314. ISceneEntity[] entities = m_scene.Entities.GetEntities();
  315. foreach (ISceneEntity group in entities)
  316. {
  317. group.CreateScriptInstances(0, false, StateSource.RegionStart, UUID.Zero, false);
  318. }
  319. //Now reset it
  320. LoadingPrims = false;
  321. }
  322. #endregion
  323. #region Public members
  324. /// <summary>
  325. /// Are we currently loading prims?
  326. /// </summary>
  327. public bool LoadingPrims
  328. {
  329. get { return m_LoadingPrims; }
  330. set { m_LoadingPrims = value; }
  331. }
  332. /// <summary>
  333. /// Delete every object from the scene. This does not include attachments worn by avatars.
  334. /// </summary>
  335. public void DeleteAllSceneObjects()
  336. {
  337. try
  338. {
  339. LoadingPrims = true;
  340. List<ISceneEntity> groups = new List<ISceneEntity>();
  341. lock (m_scene.Entities)
  342. {
  343. ISceneEntity[] entities = m_scene.Entities.GetEntities();
  344. groups.AddRange(entities.Where(entity => !entity.IsAttachment));
  345. }
  346. //Delete all the groups now
  347. DeleteSceneObjects(groups.ToArray(), true, true);
  348. //Now remove the entire region at once
  349. m_scene.SimulationDataService.RemoveRegion();
  350. LoadingPrims = false;
  351. }
  352. catch
  353. {
  354. }
  355. }
  356. public void ResetRegionToStartupDefault()
  357. {
  358. //Add the loading prims piece just to be safe
  359. LoadingPrims = true;
  360. try
  361. {
  362. lock (m_scene.Entities)
  363. {
  364. ISceneEntity[] entities = m_scene.Entities.GetEntities();
  365. foreach (ISceneEntity entity in entities)
  366. {
  367. if (!entity.IsAttachment)
  368. {
  369. List<ISceneChildEntity> parts = new List<ISceneChildEntity>();
  370. parts.AddRange(entity.ChildrenEntities());
  371. DeleteSceneObject(entity, true, false); //Don't remove from the database
  372. m_scene.ForEachScenePresence(
  373. avatar =>
  374. avatar.ControllingClient.SendKillObject(m_scene.RegionInfo.RegionHandle,
  375. parts.ToArray()));
  376. }
  377. }
  378. }
  379. }
  380. catch
  381. {
  382. }
  383. LoadingPrims = false;
  384. }
  385. /// <summary>
  386. /// Synchronously delete the objects from the scene.
  387. /// This does send kill object updates and resets the parcel prim counts.
  388. /// </summary>
  389. /// <param name="groups"></param>
  390. /// <param name="deleteScripts"></param>
  391. /// <param name="sendKillPackets"></param>
  392. /// <returns></returns>
  393. public bool DeleteSceneObjects(ISceneEntity[] groups, bool deleteScripts, bool sendKillPackets)
  394. {
  395. List<ISceneChildEntity> parts = new List<ISceneChildEntity>();
  396. foreach (ISceneEntity grp in groups)
  397. {
  398. if (grp == null)
  399. continue;
  400. //if (group.IsAttachment)
  401. // continue;
  402. parts.AddRange(grp.ChildrenEntities());
  403. DeleteSceneObject(grp, true, true);
  404. }
  405. if (sendKillPackets)
  406. {
  407. m_scene.ForEachScenePresence(avatar => avatar.ControllingClient.SendKillObject(
  408. m_scene.RegionInfo.RegionHandle, parts.ToArray()));
  409. }
  410. return true;
  411. }
  412. /// <summary>
  413. /// Add a backup taint to the prim
  414. /// </summary>
  415. /// <param name="sceneObjectGroup"></param>
  416. public void AddPrimBackupTaint(ISceneEntity sceneObjectGroup)
  417. {
  418. //Tell the database that something has changed
  419. m_scene.SimulationDataService.Tainted();
  420. }
  421. #endregion
  422. #region Per Object Methods
  423. /// <summary>
  424. /// Synchronously delete the given object from the scene.
  425. /// </summary>
  426. /// <param name="group">Object Id</param>
  427. /// <param name="DeleteScripts">Remove the scripts from the ScriptEngine as well</param>
  428. /// <param name="removeFromDatabase">Remove from the database?</param>
  429. protected bool DeleteSceneObject(ISceneEntity group, bool DeleteScripts, bool removeFromDatabase)
  430. {
  431. //MainConsole.Instance.DebugFormat("[Backup]: Deleting scene object {0} {1}", group.Name, group.UUID);
  432. if (group.SitTargetAvatar.Count != 0)
  433. {
  434. foreach (UUID avID in group.SitTargetAvatar)
  435. {
  436. //Don't screw up avatar's that are sitting on us!
  437. IScenePresence SP = m_scene.GetScenePresence(avID);
  438. if (SP != null)
  439. SP.StandUp();
  440. }
  441. }
  442. // Serialise calls to RemoveScriptInstances to avoid
  443. // deadlocking on m_parts inside SceneObjectGroup
  444. if (DeleteScripts)
  445. {
  446. group.RemoveScriptInstances(true);
  447. }
  448. foreach (ISceneChildEntity part in group.ChildrenEntities())
  449. {
  450. IScriptControllerModule m = m_scene.RequestModuleInterface<IScriptControllerModule>();
  451. if (m != null)
  452. m.RemoveAllScriptControllers(part);
  453. }
  454. if (group.RootChild.PhysActor != null)
  455. {
  456. //Remove us from the physics sim
  457. m_scene.PhysicsScene.DeletePrim(group.RootChild.PhysActor);
  458. //We MUST leave this to the PhysicsScene or it will hate us forever!
  459. //group.RootChild.PhysActor = null;
  460. }
  461. if (!group.IsAttachment)
  462. m_scene.SimulationDataService.Tainted();
  463. if (m_scene.SceneGraph.DeleteEntity(group))
  464. {
  465. // We need to keep track of this state in case this group is still queued for backup.
  466. group.IsDeleted = true;
  467. m_scene.EventManager.TriggerObjectBeingRemovedFromScene(group);
  468. return true;
  469. }
  470. //MainConsole.Instance.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID);
  471. return false;
  472. }
  473. #endregion
  474. #region IAuroraBackupModule Methods
  475. private bool m_isArchiving = false;
  476. private readonly List<UUID> m_missingAssets = new List<UUID>();
  477. private readonly List<LandData> m_parcels = new List<LandData>();
  478. private bool m_merge = false;
  479. private bool m_loadAssets = false;
  480. private GenericAccountCache<UserAccount> m_cache = new GenericAccountCache<UserAccount>();
  481. private List<ISceneEntity> m_groups = new List<ISceneEntity>();
  482. public bool IsArchiving
  483. {
  484. get { return m_isArchiving; }
  485. }
  486. public void SaveModuleToArchive(TarArchiveWriter writer, IScene scene)
  487. {
  488. m_isArchiving = true;
  489. MainConsole.Instance.Info("[Archive]: Writing parcels to archive");
  490. writer.WriteDir("parcels");
  491. IParcelManagementModule module = scene.RequestModuleInterface<IParcelManagementModule>();
  492. if (module != null)
  493. {
  494. List<ILandObject> landObject = module.AllParcels();
  495. foreach (ILandObject parcel in landObject)
  496. {
  497. OSDMap parcelMap = parcel.LandData.ToOSD();
  498. writer.WriteFile("parcels/" + parcel.LandData.GlobalID.ToString(),
  499. OSDParser.SerializeLLSDBinary(parcelMap));
  500. parcelMap = null;
  501. }
  502. }
  503. MainConsole.Instance.Info("[Archive]: Finished writing parcels to archive");
  504. MainConsole.Instance.Info("[Archive]: Writing terrain to archive");
  505. writer.WriteDir("newstyleterrain");
  506. writer.WriteDir("newstylerevertterrain");
  507. writer.WriteDir("newstylewater");
  508. writer.WriteDir("newstylerevertwater");
  509. ITerrainModule tModule = scene.RequestModuleInterface<ITerrainModule>();
  510. if (tModule != null)
  511. {
  512. try
  513. {
  514. byte[] sdata = WriteTerrainToStream(tModule.TerrainMap);
  515. writer.WriteFile("newstyleterrain/" + scene.RegionInfo.RegionID.ToString() + ".terrain", sdata);
  516. sdata = null;
  517. sdata = WriteTerrainToStream(tModule.TerrainRevertMap);
  518. writer.WriteFile("newstylerevertterrain/" + scene.RegionInfo.RegionID.ToString() + ".terrain",
  519. sdata);
  520. sdata = null;
  521. if (tModule.TerrainWaterMap != null)
  522. {
  523. sdata = WriteTerrainToStream(tModule.TerrainWaterMap);
  524. writer.WriteFile("newstylewater/" + scene.RegionInfo.RegionID.ToString() + ".terrain", sdata);
  525. sdata = null;
  526. sdata = WriteTerrainToStream(tModule.TerrainWaterRevertMap);
  527. writer.WriteFile(
  528. "newstylerevertwater/" + scene.RegionInfo.RegionID.ToString() + ".terrain", sdata);
  529. sdata = null;
  530. }
  531. }
  532. catch (Exception ex)
  533. {
  534. MainConsole.Instance.WarnFormat("[Backup]: Exception caught: {0}", ex.ToString());
  535. }
  536. }
  537. MainConsole.Instance.Info("[Archive]: Finished writing terrain to archive");
  538. MainConsole.Instance.Info("[Archive]: Writing entities to archive");
  539. ISceneEntity[] entities = scene.Entities.GetEntities();
  540. //Get all entities, then start writing them to the database
  541. writer.WriteDir("entities");
  542. IDictionary<UUID, AssetType> assets = new Dictionary<UUID, AssetType>();
  543. UuidGatherer assetGatherer = new UuidGatherer(m_scene.AssetService);
  544. IAuroraBackupArchiver archiver = m_scene.RequestModuleInterface<IAuroraBackupArchiver>();
  545. bool saveAssets = false;
  546. if (archiver.AllowPrompting)
  547. saveAssets =
  548. MainConsole.Instance.Prompt("Save assets? (Will not be able to load on other grids)", "false")
  549. .Equals("true", StringComparison.CurrentCultureIgnoreCase);
  550. int count = 0;
  551. foreach (ISceneEntity entity in entities)
  552. {
  553. try
  554. {
  555. if (entity.IsAttachment ||
  556. ((entity.RootChild.Flags & PrimFlags.Temporary) == PrimFlags.Temporary)
  557. || ((entity.RootChild.Flags & PrimFlags.TemporaryOnRez) == PrimFlags.TemporaryOnRez))
  558. continue;
  559. //Write all entities
  560. byte[] xml = entity.ToBinaryXml2();
  561. writer.WriteFile("entities/" + entity.UUID.ToString(), xml);
  562. xml = null;
  563. count++;
  564. if (count%3 == 0)
  565. Thread.Sleep(5);
  566. //Get all the assets too
  567. if (saveAssets)
  568. assetGatherer.GatherAssetUuids(entity, assets, scene);
  569. }
  570. catch (Exception ex)
  571. {
  572. MainConsole.Instance.WarnFormat("[Backup]: Exception caught: {0}", ex);
  573. }
  574. }
  575. entities = null;
  576. MainConsole.Instance.Info("[Archive]: Finished writing entities to archive");
  577. MainConsole.Instance.Info("[Archive]: Writing assets for entities to archive");
  578. bool foundAllAssets = true;
  579. foreach (UUID assetID in new List<UUID>(assets.Keys))
  580. {
  581. try
  582. {
  583. foundAllAssets = false; //Not all are cached
  584. m_scene.AssetService.Get(assetID.ToString(), writer, RetrievedAsset);
  585. m_missingAssets.Add(assetID);
  586. }
  587. catch (Exception ex)
  588. {
  589. MainConsole.Instance.WarnFormat("[Backup]: Exception caught: {0}", ex);
  590. }
  591. }
  592. if (foundAllAssets)
  593. m_isArchiving = false; //We're done if all the assets were found
  594. MainConsole.Instance.Info("[Archive]: Finished writing assets for entities to archive");
  595. }
  596. private static byte[] WriteTerrainToStream(ITerrainChannel tModule)
  597. {
  598. int tMapSize = tModule.Height*tModule.Height;
  599. byte[] sdata = new byte[tMapSize*2];
  600. Buffer.BlockCopy(tModule.GetSerialised(tModule.Scene), 0, sdata, 0, sdata.Length);
  601. return sdata;
  602. }
  603. private void RetrievedAsset(string id, Object sender, AssetBase asset)
  604. {
  605. TarArchiveWriter writer = (TarArchiveWriter) sender;
  606. //Add the asset
  607. WriteAsset(id, asset, writer);
  608. m_missingAssets.Remove(UUID.Parse(id));
  609. if (m_missingAssets.Count == 0)
  610. m_isArchiving = false;
  611. }
  612. private void WriteAsset(string id, AssetBase asset, TarArchiveWriter writer)
  613. {
  614. if (asset != null)
  615. writer.WriteFile("assets/" + asset.ID, OSDParser.SerializeJsonString(asset.ToOSD()));
  616. else
  617. MainConsole.Instance.WarnFormat("Could not find asset {0}", id);
  618. }
  619. public void BeginLoadModuleFromArchive(IScene scene)
  620. {
  621. IBackupModule backup = scene.RequestModuleInterface<IBackupModule>();
  622. IScriptModule[] modules = scene.RequestModuleInterfaces<IScriptModule>();
  623. IParcelManagementModule parcelModule = scene.RequestModuleInterface<IParcelManagementModule>();
  624. //Disable the script engine so that it doesn't load in the background and kill OAR loading
  625. foreach (IScriptModule module in modules)
  626. {
  627. if (module != null)
  628. module.Disabled = true;
  629. }
  630. //Disable backup for now as well
  631. if (backup != null)
  632. {
  633. backup.LoadingPrims = true;
  634. m_loadAssets =
  635. MainConsole.Instance.Prompt(
  636. "Should any stored assets be loaded? (If you got this .abackup from another grid, choose yes",
  637. "no").ToLower() == "yes";
  638. m_merge =
  639. MainConsole.Instance.Prompt(
  640. "Should we merge prims together (keep the prims from the old region too)?", "no").ToLower() ==
  641. "yes";
  642. if (!m_merge)
  643. {
  644. DateTime before = DateTime.Now;
  645. MainConsole.Instance.Info("[ARCHIVER]: Clearing all existing scene objects");
  646. backup.DeleteAllSceneObjects();
  647. MainConsole.Instance.Info("[ARCHIVER]: Cleared all existing scene objects in " +
  648. (DateTime.Now - before).Minutes + ":" +
  649. (DateTime.Now - before).Seconds);
  650. if (parcelModule != null)
  651. parcelModule.ClearAllParcels();
  652. }
  653. }
  654. }
  655. public void EndLoadModuleFromArchive(IScene scene)
  656. {
  657. IBackupModule backup = scene.RequestModuleInterface<IBackupModule>();
  658. IScriptModule[] modules = scene.RequestModuleInterfaces<IScriptModule>();
  659. //Reeanble now that we are done
  660. foreach (IScriptModule module in modules)
  661. {
  662. module.Disabled = false;
  663. }
  664. //Reset backup too
  665. if (backup != null)
  666. backup.LoadingPrims = false;
  667. //Update the database as well!
  668. IParcelManagementModule parcelManagementModule = scene.RequestModuleInterface<IParcelManagementModule>();
  669. if (parcelManagementModule != null && !m_merge) //Only if we are not merging
  670. {
  671. if (m_parcels.Count > 0)
  672. {
  673. scene.EventManager.TriggerIncomingLandDataFromStorage(m_parcels, Vector2.Zero);
  674. //Update the database as well!
  675. foreach (LandData parcel in m_parcels)
  676. {
  677. parcelManagementModule.UpdateLandObject(parcelManagementModule.GetLandObject(parcel.LocalID));
  678. }
  679. }
  680. else parcelManagementModule.ResetSimLandObjects();
  681. m_parcels.Clear();
  682. }
  683. foreach (ISceneEntity sceneObject in m_groups)
  684. {
  685. foreach (ISceneChildEntity part in sceneObject.ChildrenEntities())
  686. {
  687. if (!ResolveUserUuid(part.CreatorID))
  688. part.CreatorID = m_scene.RegionInfo.EstateSettings.EstateOwner;
  689. if (!ResolveUserUuid(part.OwnerID))
  690. part.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
  691. if (!ResolveUserUuid(part.LastOwnerID))
  692. part.LastOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
  693. // Fix ownership/creator of inventory items
  694. // Not doing so results in inventory items
  695. // being no copy/no mod for everyone
  696. lock (part.TaskInventory)
  697. {
  698. TaskInventoryDictionary inv = part.TaskInventory;
  699. foreach (KeyValuePair<UUID, TaskInventoryItem> kvp in inv)
  700. {
  701. if (!ResolveUserUuid(kvp.Value.OwnerID))
  702. {
  703. kvp.Value.OwnerID = scene.RegionInfo.EstateSettings.EstateOwner;
  704. }
  705. if (!ResolveUserUuid(kvp.Value.CreatorID))
  706. {
  707. kvp.Value.CreatorID = scene.RegionInfo.EstateSettings.EstateOwner;
  708. }
  709. }
  710. }
  711. }
  712. if (scene.SceneGraph.AddPrimToScene(sceneObject))
  713. {
  714. sceneObject.HasGroupChanged = true;
  715. sceneObject.ScheduleGroupUpdate(PrimUpdateFlags.ForcedFullUpdate);
  716. sceneObject.CreateScriptInstances(0, false, StateSource.RegionStart, UUID.Zero, false);
  717. }
  718. }
  719. }
  720. public void LoadModuleFromArchive(byte[] data, string filePath, TarArchiveReader.TarEntryType type,
  721. IScene scene)
  722. {
  723. if (filePath.StartsWith("parcels/"))
  724. {
  725. if (!m_merge)
  726. {
  727. //Only use if we are not merging
  728. LandData parcel = new LandData();
  729. OSD parcelData = OSDParser.DeserializeLLSDBinary(data);
  730. parcel.FromOSD((OSDMap) parcelData);
  731. m_parcels.Add(parcel);
  732. }
  733. }
  734. #region New Style Terrain Loading
  735. else if (filePath.StartsWith("newstyleterrain/"))
  736. {
  737. ITerrainModule terrainModule = scene.RequestModuleInterface<ITerrainModule>();
  738. terrainModule.TerrainMap = ReadTerrain(data, scene);
  739. }
  740. else if (filePath.StartsWith("newstylerevertterrain/"))
  741. {
  742. ITerrainModule terrainModule = scene.RequestModuleInterface<ITerrainModule>();
  743. terrainModule.TerrainRevertMap = ReadTerrain(data, scene);
  744. }
  745. else if (filePath.StartsWith("newstylewater/"))
  746. {
  747. ITerrainModule terrainModule = scene.RequestModuleInterface<ITerrainModule>();
  748. terrainModule.TerrainWaterMap = ReadTerrain(data, scene);
  749. }
  750. else if (filePath.StartsWith("newstylerevertwater/"))
  751. {
  752. ITerrainModule terrainModule = scene.RequestModuleInterface<ITerrainModule>();
  753. terrainModule.TerrainWaterRevertMap = ReadTerrain(data, scene);
  754. }
  755. #endregion
  756. #region Old Style Terrain Loading
  757. else if (filePath.StartsWith("terrain/"))
  758. {
  759. ITerrainModule terrainModule = scene.RequestModuleInterface<ITerrainModule>();
  760. MemoryStream ms = new MemoryStream(data);
  761. terrainModule.LoadFromStream(filePath, ms, 0, 0);
  762. ms.Close();
  763. }
  764. else if (filePath.StartsWith("revertterrain/"))
  765. {
  766. ITerrainModule terrainModule = scene.RequestModuleInterface<ITerrainModule>();
  767. MemoryStream ms = new MemoryStream(data);
  768. terrainModule.LoadRevertMapFromStream(filePath, ms, 0, 0);
  769. ms.Close();
  770. }
  771. else if (filePath.StartsWith("water/"))
  772. {
  773. ITerrainModule terrainModule = scene.RequestModuleInterface<ITerrainModule>();
  774. MemoryStream ms = new MemoryStream(data);
  775. terrainModule.LoadWaterFromStream(filePath, ms, 0, 0);
  776. ms.Close();
  777. }
  778. else if (filePath.StartsWith("revertwater/"))
  779. {
  780. ITerrainModule terrainModule = scene.RequestModuleInterface<ITerrainModule>();
  781. MemoryStream ms = new MemoryStream(data);
  782. terrainModule.LoadWaterRevertMapFromStream(filePath, ms, 0, 0);
  783. ms.Close();
  784. }
  785. #endregion
  786. else if (filePath.StartsWith("entities/"))
  787. {
  788. MemoryStream ms = new MemoryStream(data);
  789. ISceneEntity sceneObject = SceneEntitySerializer.SceneObjectSerializer.FromXml2Format(ref ms, scene);
  790. ms.Close();
  791. ms = null;
  792. data = null;
  793. m_groups.Add(sceneObject);
  794. }
  795. else if (filePath.StartsWith("assets/"))
  796. {
  797. if (m_loadAssets)
  798. {
  799. AssetBase asset = new AssetBase();
  800. asset.Unpack(OSDParser.DeserializeJson(Encoding.UTF8.GetString(data)));
  801. scene.AssetService.Store(asset);
  802. }
  803. }
  804. }
  805. private ITerrainChannel ReadTerrain(byte[] data, IScene scene)
  806. {
  807. short[] sdata = new short[data.Length/2];
  808. Buffer.BlockCopy(data, 0, sdata, 0, data.Length);
  809. return new TerrainChannel(sdata, scene);
  810. }
  811. private bool ResolveUserUuid(UUID uuid)
  812. {
  813. UserAccount acc;
  814. if (m_cache.Get(uuid, out acc))
  815. return acc != null;
  816. acc = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.AllScopeIDs, uuid);
  817. m_cache.Cache(uuid, acc);
  818. return acc != null;
  819. }
  820. #endregion
  821. }
  822. #endregion
  823. }
  824. }