public static void PackageArchive(string directoryName, string filename, bool includeTerrain, bool includeLandData) { const string ARCHIVE_XML = "<?xml version=\"1.0\" encoding=\"utf-16\"?>\n<archive major_version=\"0\" minor_version=\"1\" />"; TarArchiveWriter archive = new TarArchiveWriter(); // Create the archive.xml file archive.AddFile("archive.xml", ARCHIVE_XML); // Add the assets string[] files = Directory.GetFiles(directoryName + "/assets"); foreach (string file in files) archive.AddFile("assets/" + Path.GetFileName(file), File.ReadAllBytes(file)); // Add the objects files = Directory.GetFiles(directoryName + "/objects"); foreach (string file in files) archive.AddFile("objects/" + Path.GetFileName(file), File.ReadAllBytes(file)); // Add the terrain(s) files = Directory.GetFiles(directoryName + "/terrains"); if (includeTerrain) foreach (string file in files) archive.AddFile("terrains/" + Path.GetFileName(file), File.ReadAllBytes(file)); // Add the terrain(s) files = Directory.GetFiles(directoryName + "/landdata"); if (includeLandData) foreach (string file in files) archive.AddFile("landdata/" + Path.GetFileName(file), File.ReadAllBytes(file)); File.Delete(filename); archive.WriteTar(new GZipStream(new FileStream(filename, FileMode.Create), CompressionMode.Compress)); }
/// <summary> /// Archive the region requested. /// </summary> /// <exception cref="System.IO.IOException">if there was an io problem with creating the file</exception> public void ArchiveRegion() { Dictionary <UUID, AssetType> assetUuids = new Dictionary <UUID, AssetType>(); ISceneEntity[] entities = m_scene.Entities.GetEntities(); List <ISceneEntity> sceneObjects = new List <ISceneEntity>(); int numObjectsSkippedPermissions = 0; // Filter entities so that we only have scene objects. // FIXME: Would be nicer to have this as a proper list in SceneGraph, since lots of methods // end up having to do this foreach (ISceneEntity entity in entities.Where(entity => !entity.IsDeleted && !entity.IsAttachment)) { if (!CanUserArchiveObject(m_scene.RegionInfo.EstateSettings.EstateOwner, entity, m_checkPermissions)) { // The user isn't allowed to copy/transfer this object, so it will not be included in the OAR. ++numObjectsSkippedPermissions; } else { sceneObjects.Add(entity); } } UuidGatherer assetGatherer = new UuidGatherer(m_scene.AssetService); foreach (ISceneEntity sceneObject in sceneObjects) { assetGatherer.GatherAssetUuids(sceneObject, assetUuids); } MainConsole.Instance.InfoFormat( "[Archiver]: {0} scene objects to serialize requiring save of {1} assets", sceneObjects.Count, assetUuids.Count); if (numObjectsSkippedPermissions > 0) { MainConsole.Instance.DebugFormat( "[Archiver]: {0} scene objects skipped due to lack of permissions", numObjectsSkippedPermissions); } // Make sure that we also request terrain texture assets RegionSettings regionSettings = m_scene.RegionInfo.RegionSettings; if (regionSettings.TerrainTexture1 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_1) { assetUuids[regionSettings.TerrainTexture1] = AssetType.Texture; } if (regionSettings.TerrainTexture2 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_2) { assetUuids[regionSettings.TerrainTexture2] = AssetType.Texture; } if (regionSettings.TerrainTexture3 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_3) { assetUuids[regionSettings.TerrainTexture3] = AssetType.Texture; } if (regionSettings.TerrainTexture4 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_4) { assetUuids[regionSettings.TerrainTexture4] = AssetType.Texture; } TarArchiveWriter archiveWriter = new TarArchiveWriter(m_saveStream); // Asynchronously request all the assets required to perform this archive operation ArchiveWriteRequestExecution awre = new ArchiveWriteRequestExecution( sceneObjects, m_scene.RequestModuleInterface <ITerrainModule>(), m_scene.RequestModuleInterface <IRegionSerialiserModule>(), m_scene, archiveWriter, m_requestId); new AssetsRequest( new AssetsArchiver(archiveWriter), assetUuids, m_scene.AssetService, awre.ReceivedAllAssets).Execute(); }
/// <summary> /// Archive the region requested. /// </summary> /// <exception cref="System.IO.IOException">if there was an io problem with creating the file</exception> public void ArchiveRegion() { Dictionary <UUID, int> assetUuids = new Dictionary <UUID, int>(); List <EntityBase> entities = m_scene.GetEntities(); List <SceneObjectGroup> sceneObjects = new List <SceneObjectGroup>(); // Filter entities so that we only have scene objects. // FIXME: Would be nicer to have this as a proper list in SceneGraph, since lots of methods // end up having to do this foreach (EntityBase entity in entities) { if (entity is SceneObjectGroup) { SceneObjectGroup sceneObject = (SceneObjectGroup)entity; if (MustCheckCreatorIds) { bool failedCreatorCheck = false; foreach (SceneObjectPart part in sceneObject.GetParts()) { if (!ExportIsAllowed(part.CreatorID)) { failedCreatorCheck = true; break; } } if (failedCreatorCheck) { continue; } } if (!sceneObject.IsDeleted && !sceneObject.IsAttachment) { sceneObjects.Add(sceneObject); } } } if (m_storeAssets) { UuidGatherer assetGatherer = new UuidGatherer(m_scene.CommsManager.AssetCache); foreach (SceneObjectGroup sceneObject in sceneObjects) { assetGatherer.GatherAssetUuids(sceneObject, assetUuids); } } // Make sure that we also request terrain texture assets RegionSettings regionSettings = m_scene.RegionInfo.RegionSettings; if (m_storeAssets) { if (regionSettings.TerrainTexture1 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_1) { assetUuids[regionSettings.TerrainTexture1] = 1; } if (regionSettings.TerrainTexture2 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_2) { assetUuids[regionSettings.TerrainTexture2] = 1; } if (regionSettings.TerrainTexture3 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_3) { assetUuids[regionSettings.TerrainTexture3] = 1; } if (regionSettings.TerrainTexture4 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_4) { assetUuids[regionSettings.TerrainTexture4] = 1; } } if (MustCheckCreatorIds) { int originalCount = assetUuids.Count; m_log.DebugFormat( "[ARCHIVER]: Filtering {0} asset IDs for {1} allowed creators", originalCount, m_allowedCreatorIds.Count); C5.HashSet <UUID> assetsCreatedByAllowedUsers = this.CollectCreatedAssetIdsFromUserInventories(); IEnumerable <UUID> uuids = new List <UUID>(assetUuids.Keys); assetUuids.Clear(); foreach (UUID assetId in uuids) { if (assetsCreatedByAllowedUsers.Contains(assetId)) { assetUuids.Add(assetId, 1); } } m_log.DebugFormat( "[ARCHIVER]: Allowing export of {0} of {1} assets", assetUuids.Count, originalCount); } m_log.DebugFormat( "[ARCHIVER]: {0} scene objects to serialize requiring save of {1} assets", sceneObjects.Count, assetUuids.Count); TarArchiveWriter archiveWriter = new TarArchiveWriter(m_saveStream); // Asynchronously request all the assets required to perform this archive operation ArchiveWriteRequestExecution awre = new ArchiveWriteRequestExecution( sceneObjects, m_scene.RequestModuleInterface <ITerrainModule>(), m_scene.RequestModuleInterface <IRegionSerializerModule>(), m_scene, archiveWriter, m_requestId); new AssetsRequest( new AssetsArchiver(archiveWriter), assetUuids.Keys, m_scene.CommsManager.AssetCache, awre.ReceivedAllAssets).Execute(); }
public void TestLoadIarV0p1TempProfiles() { Assert.Ignore(); TestHelper.InMethod(); Console.WriteLine("### Started {0} ###", MethodBase.GetCurrentMethod()); log4net.Config.XmlConfigurator.Configure(); string userFirstName = "Dennis"; string userLastName = "Menace"; UUID userUuid = UUID.Parse("00000000-0000-0000-0000-000000000aaa"); string user2FirstName = "Walter"; string user2LastName = "Mitty"; string itemName = "b.lsl"; string archiveItemName = string.Format("{0}{1}{2}", itemName, "_", UUID.Random()); MemoryStream archiveWriteStream = new MemoryStream(); TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream); InventoryItemBase item1 = new InventoryItemBase(); item1.Name = itemName; item1.AssetID = UUID.Random(); item1.GroupID = UUID.Random(); item1.CreatorId = OspResolver.MakeOspa(user2FirstName, user2LastName); item1.Owner = UUID.Zero; string item1FileName = string.Format("{0}{1}", ArchiveConstants.INVENTORY_PATH, archiveItemName); tar.WriteFile(item1FileName, UserInventoryItemSerializer.Serialize(item1)); tar.Close(); MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray()); SerialiserModule serialiserModule = new SerialiserModule(); InventoryArchiverModule archiverModule = new InventoryArchiverModule(); // Annoyingly, we have to set up a scene even though inventory loading has nothing to do with a scene Scene scene = SceneSetupHelpers.SetupScene(); IUserAdminService userAdminService = scene.CommsManager.UserAdminService; SceneSetupHelpers.SetupSceneModules(scene, serialiserModule, archiverModule); userAdminService.AddUser( userFirstName, userLastName, "meowfood", String.Empty, 1000, 1000, userUuid); archiverModule.DearchiveInventory(userFirstName, userLastName, "/", archiveReadStream); // Check that a suitable temporary user profile has been created. UserProfileData user2Profile = scene.CommsManager.UserService.GetUserProfile( OspResolver.HashName(user2FirstName + " " + user2LastName)); Assert.That(user2Profile, Is.Not.Null); Assert.That(user2Profile.FirstName == user2FirstName); Assert.That(user2Profile.SurName == user2LastName); CachedUserInfo userInfo = scene.CommsManager.UserProfileCacheService.GetUserDetails(userFirstName, userLastName); InventoryItemBase foundItem = userInfo.RootFolder.FindItemByPath(itemName); Assert.That(foundItem.CreatorId, Is.EqualTo(item1.CreatorId)); Assert.That( foundItem.CreatorIdAsUuid, Is.EqualTo(OspResolver.HashName(user2FirstName + " " + user2LastName))); Assert.That(foundItem.Owner, Is.EqualTo(userUuid)); Console.WriteLine("### Successfully completed {0} ###", MethodBase.GetCurrentMethod()); }
public static void Save( UGUI principal, InventoryServiceInterface inventoryService, AssetServiceInterface assetService, List <AvatarNameServiceInterface> nameServices, SaveOptions options, Stream outputFile, string frompath, TTY console_io = null) { UUID parentFolder; Dictionary <UUID, KeyValuePair <string, UUID> > folders = new Dictionary <UUID, KeyValuePair <string, UUID> >(); parentFolder = inventoryService.Folder[principal.ID, AssetType.RootFolder].ID; if (!frompath.StartsWith("/")) { throw new InvalidInventoryPathException(); } foreach (string pathcomp in frompath.Substring(1).Split('/')) { List <InventoryFolder> childfolders = inventoryService.Folder.GetFolders(principal.ID, parentFolder); int idx; for (idx = 0; idx < childfolders.Count; ++idx) { if (pathcomp.ToLower() == childfolders[idx].Name.ToLower()) { break; } } if (idx == childfolders.Count) { throw new InvalidInventoryPathException(); } parentFolder = childfolders[idx].ID; folders[parentFolder] = new KeyValuePair <string, UUID>(childfolders[idx].Name, UUID.Zero); } using (GZipStream gzip = new GZipStream(outputFile, CompressionMode.Compress)) { TarArchiveWriter writer = new TarArchiveWriter(gzip); bool saveAssets = (options & SaveOptions.NoAssets) == 0; if (console_io != null) { console_io.Write("Saving archive info..."); } writer.WriteFile("archive.xml", WriteArchiveXml(saveAssets)); List <UUID> nextFolders = new List <UUID>(); List <UUID> assetIds = new List <UUID>(); nextFolders.Add(parentFolder); if (console_io != null) { console_io.Write("Saving inventory data..."); } while (nextFolders.Count != 0) { InventoryFolderContent content; UUID folderId = nextFolders[0]; nextFolders.RemoveAt(0); content = inventoryService.Folder.Content[principal.ID, folderId]; foreach (InventoryFolder folder in content.Folders) { folders[folder.ID] = new KeyValuePair <string, UUID>(folder.Name, folderId); } foreach (InventoryItem item in content.Items) { if (item.AssetType != AssetType.Link && item.AssetType != AssetType.LinkFolder && !assetIds.Contains(item.AssetID) && saveAssets) { assetIds.Add(item.AssetID); } writer.WriteFile(GetFolderPath(folders, item), WriteInventoryItem(item)); } } if (saveAssets) { if (console_io != null) { console_io.Write("Saving asset data..."); } /* we only parse sim details when saving assets */ AssetData data; int assetidx = 0; while (assetidx < assetIds.Count) { UUID assetID = assetIds[assetidx++]; try { data = assetService[assetID]; } catch { continue; } writer.WriteAsset(data); try { foreach (UUID refid in data.References) { if (!assetIds.Contains(refid)) { assetIds.Add(refid); } } } catch { console_io.WriteFormatted("Failed to parse asset {0}", assetID); } } } } }
private void WriteAsset(AssetBase asset, TarArchiveWriter writer) { writer.WriteFile("assets", asset.Data); }
/// <summary> /// Archive the region requested. /// </summary> /// <exception cref="System.IO.IOException">if there was an io problem with creating the file</exception> public void ArchiveRegion() { Dictionary <UUID, AssetType> assetUuids = new Dictionary <UUID, AssetType>(); List <EntityBase> entities = m_scene.GetEntities(); List <SceneObjectGroup> sceneObjects = new List <SceneObjectGroup>(); /* * foreach (ILandObject lo in m_scene.LandChannel.AllParcels()) * { * if (name == lo.LandData.Name) * { * // This is the parcel we want * } * } */ // Filter entities so that we only have scene objects. // FIXME: Would be nicer to have this as a proper list in SceneGraph, since lots of methods // end up having to do this foreach (EntityBase entity in entities) { if (entity is SceneObjectGroup) { SceneObjectGroup sceneObject = (SceneObjectGroup)entity; if (!sceneObject.IsDeleted && !sceneObject.IsAttachment) { sceneObjects.Add((SceneObjectGroup)entity); } } } UuidGatherer assetGatherer = new UuidGatherer(m_scene.AssetService); foreach (SceneObjectGroup sceneObject in sceneObjects) { assetGatherer.GatherAssetUuids(sceneObject, assetUuids); } m_log.DebugFormat( "[ARCHIVER]: {0} scene objects to serialize requiring save of {1} assets", sceneObjects.Count, assetUuids.Count); // Make sure that we also request terrain texture assets RegionSettings regionSettings = m_scene.RegionInfo.RegionSettings; if (regionSettings.TerrainTexture1 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_1) { assetUuids[regionSettings.TerrainTexture1] = AssetType.Texture; } if (regionSettings.TerrainTexture2 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_2) { assetUuids[regionSettings.TerrainTexture2] = AssetType.Texture; } if (regionSettings.TerrainTexture3 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_3) { assetUuids[regionSettings.TerrainTexture3] = AssetType.Texture; } if (regionSettings.TerrainTexture4 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_4) { assetUuids[regionSettings.TerrainTexture4] = AssetType.Texture; } TarArchiveWriter archiveWriter = new TarArchiveWriter(m_saveStream); // Asynchronously request all the assets required to perform this archive operation ArchiveWriteRequestExecution awre = new ArchiveWriteRequestExecution( sceneObjects, m_scene.RequestModuleInterface <ITerrainModule>(), m_scene.RequestModuleInterface <IRegionSerialiserModule>(), m_scene, archiveWriter, m_requestId); new AssetsRequest( new AssetsArchiver(archiveWriter), assetUuids, m_scene.AssetService, awre.ReceivedAllAssets).Execute(); }
/// <summary> /// Execute the inventory write request /// </summary> public void Execute() { try { InventoryFolderBase inventoryFolder = null; InventoryItemBase inventoryItem = null; InventoryFolderBase rootFolder = m_inventoryService.GetRootFolder(m_userInfo.PrincipalID); if (rootFolder == null) { MainConsole.Instance.ErrorFormat("[Inventory Archiver]: Unable to fine root folder for {0}", m_userInfo.PrincipalID); return; } if (m_defaultFolderToSave != null) { rootFolder = m_defaultFolderToSave; } bool saveFolderContentsOnly = false; // Eliminate double slashes and any leading / on the path. string[] components = m_invPath.Split( new[] { InventoryFolderImpl.PATH_DELIMITER }, StringSplitOptions.RemoveEmptyEntries); int maxComponentIndex = components.Length - 1; // If the path terminates with a STAR then later on we want to archive all nodes in the folder but not the // folder itself. This may get more sophisicated later on if (maxComponentIndex >= 0 && components[maxComponentIndex] == STAR_WILDCARD) { saveFolderContentsOnly = true; maxComponentIndex--; } else if (maxComponentIndex == -1) { // If the user has just specified "/", then don't save the root "My Inventory" folder. This is // more intuitive then requiring the user to specify "/*" for this. // 20141119-greythane- This breaks saving default inventory // saveFolderContentsOnly = true; } m_invPath = string.Empty; for (int i = 0; i <= maxComponentIndex; i++) { m_invPath += components[i] + InventoryFolderImpl.PATH_DELIMITER; } // Annoyingly Split actually returns the original string if the input string consists only of delimiters // Therefore if we still start with a / after the split, then we need the root folder if (m_invPath.Length == 0) { inventoryFolder = rootFolder; } else { m_invPath = m_invPath.Remove(m_invPath.LastIndexOf(InventoryFolderImpl.PATH_DELIMITER, StringComparison.Ordinal)); List <InventoryFolderBase> candidateFolders = InventoryArchiveUtils.FindFolderByPath(m_inventoryService, rootFolder, m_invPath); if (candidateFolders.Count > 0) { inventoryFolder = candidateFolders[0]; } } // The path may point to an item instead if (inventoryFolder == null) { inventoryItem = InventoryArchiveUtils.FindItemByPath(m_inventoryService, rootFolder, m_invPath); //inventoryItem = m_userInfo.RootFolder.FindItemByPath(m_invPath); } if (null == inventoryFolder && null == inventoryItem) { // We couldn't find the path indicated string errorMessage = string.Format("Aborted save. Could not find inventory path {0}", m_invPath); Exception e = new InventoryArchiverException(errorMessage); if (m_module != null) { m_module.TriggerInventoryArchiveSaved(m_id, false, m_userInfo, m_invPath, m_saveStream, e); } throw e; } m_archiveWriter = new TarArchiveWriter(m_saveStream); if (inventoryFolder != null) { MainConsole.Instance.DebugFormat( "[Inventory Archiver]: Found folder {0} {1} at {2}", inventoryFolder.Name, inventoryFolder.ID, m_invPath == string.Empty ? InventoryFolderImpl.PATH_DELIMITER : m_invPath); //recurse through all dirs getting dirs and files SaveInvFolder(inventoryFolder, ArchiveConstants.INVENTORY_PATH, !saveFolderContentsOnly); } else if (inventoryItem != null) { MainConsole.Instance.DebugFormat( "[Inventory Archiver]: Found item {0} {1} at {2}", inventoryItem.Name, inventoryItem.ID, m_invPath); SaveInvItem(inventoryItem, ArchiveConstants.INVENTORY_PATH); } // Don't put all this profile information into the archive right now. //SaveUsers(); } catch (Exception) { m_saveStream.Close(); throw; } if (m_saveAssets) { foreach (AssetBase asset in m_assetsToAdd) { m_assetUuids[asset.ID] = (AssetType)asset.Type; } new AssetsRequest( new AssetsArchiver(m_archiveWriter), m_assetUuids, m_assetService, ReceivedAllAssets).Execute(); } else { MainConsole.Instance.Debug("[Inventory Archiver]: Save Complete"); m_archiveWriter.Close(); } }
/// <summary> /// Archive the region requested. /// </summary> /// <exception cref="System.IO.IOException">if there was an io problem with creating the file</exception> public void ArchiveRegion(Dictionary <string, object> options) { if (options.ContainsKey("noassets") && (bool)options["noassets"]) { SaveAssets = false; } try { Dictionary <UUID, AssetType> assetUuids = new Dictionary <UUID, AssetType>(); EntityBase[] entities = m_scene.GetEntities(); List <SceneObjectGroup> sceneObjects = new List <SceneObjectGroup>(); string checkPermissions = null; int numObjectsSkippedPermissions = 0; Object temp; if (options.TryGetValue("checkPermissions", out temp)) { checkPermissions = (string)temp; } // Filter entities so that we only have scene objects. // FIXME: Would be nicer to have this as a proper list in SceneGraph, since lots of methods // end up having to do this foreach (EntityBase entity in entities) { if (entity is SceneObjectGroup) { SceneObjectGroup sceneObject = (SceneObjectGroup)entity; if (!sceneObject.IsDeleted && !sceneObject.IsAttachment) { if (!CanUserArchiveObject(m_scene.RegionInfo.EstateSettings.EstateOwner, sceneObject, checkPermissions)) { // The user isn't allowed to copy/transfer this object, so it will not be included in the OAR. ++numObjectsSkippedPermissions; } else { sceneObjects.Add(sceneObject); } } } } if (SaveAssets) { UuidGatherer assetGatherer = new UuidGatherer(m_scene.AssetService); foreach (SceneObjectGroup sceneObject in sceneObjects) { assetGatherer.GatherAssetUuids(sceneObject, assetUuids); } m_log.DebugFormat( "[ARCHIVER]: {0} scene objects to serialize requiring save of {1} assets", sceneObjects.Count, assetUuids.Count); } else { m_log.DebugFormat("[ARCHIVER]: Not saving assets since --noassets was specified"); } if (numObjectsSkippedPermissions > 0) { m_log.DebugFormat( "[ARCHIVER]: {0} scene objects skipped due to lack of permissions", numObjectsSkippedPermissions); } // Make sure that we also request terrain texture assets RegionSettings regionSettings = m_scene.RegionInfo.RegionSettings; if (regionSettings.TerrainTexture1 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_1) { assetUuids[regionSettings.TerrainTexture1] = AssetType.Texture; } if (regionSettings.TerrainTexture2 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_2) { assetUuids[regionSettings.TerrainTexture2] = AssetType.Texture; } if (regionSettings.TerrainTexture3 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_3) { assetUuids[regionSettings.TerrainTexture3] = AssetType.Texture; } if (regionSettings.TerrainTexture4 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_4) { assetUuids[regionSettings.TerrainTexture4] = AssetType.Texture; } TarArchiveWriter archiveWriter = new TarArchiveWriter(m_saveStream); // Asynchronously request all the assets required to perform this archive operation ArchiveWriteRequestExecution awre = new ArchiveWriteRequestExecution( sceneObjects, m_scene.RequestModuleInterface <ITerrainModule>(), m_scene.RequestModuleInterface <IRegionSerialiserModule>(), m_scene, archiveWriter, m_requestId, options); m_log.InfoFormat("[ARCHIVER]: Creating archive file. This may take some time."); // Write out control file. This has to be done first so that subsequent loaders will see this file first // XXX: I know this is a weak way of doing it since external non-OAR aware tar executables will not do this archiveWriter.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, CreateControlFile(options)); m_log.InfoFormat("[ARCHIVER]: Added control file to archive."); if (SaveAssets) { new AssetsRequest( new AssetsArchiver(archiveWriter), assetUuids, m_scene.AssetService, m_scene.UserAccountService, m_scene.RegionInfo.ScopeID, options, awre.ReceivedAllAssets).Execute(); } else { awre.ReceivedAllAssets(new List <UUID>(), new List <UUID>()); } } catch (Exception) { m_saveStream.Close(); throw; } }
/// <summary> /// Archive the region requested. /// </summary> /// <exception cref="System.IO.IOException">if there was an io problem with creating the file</exception> public void ArchiveRegion() { Dictionary <UUID, int> assetUuids = new Dictionary <UUID, int>(); List <EntityBase> entities = m_scene.GetEntities(); List <SceneObjectGroup> sceneObjects = new List <SceneObjectGroup>(); List <UUID> userlist = new List <UUID>(); // Filter entities so that we only have scene objects. // FIXME: Would be nicer to have this as a proper list in SceneGraph, since lots of methods // end up having to do this foreach (EntityBase entity in entities) { if (entity is SceneObjectGroup) { SceneObjectGroup sceneObject = (SceneObjectGroup)entity; // If storing assets, assume cross-grid and include the user list file if (m_storeAssets) { AddObjectUsersToList(userlist, sceneObject); } if (MustCheckCreatorIds) { bool failedCreatorCheck = false; foreach (SceneObjectPart part in sceneObject.GetParts()) { if (!ExportIsAllowed(part.CreatorID)) { failedCreatorCheck = true; break; } } if (failedCreatorCheck) { continue; } } if (!sceneObject.IsDeleted && !sceneObject.IsAttachment) { sceneObjects.Add(sceneObject); } } } if (m_storeAssets) { UuidGatherer assetGatherer = new UuidGatherer(m_scene.CommsManager.AssetCache); foreach (SceneObjectGroup sceneObject in sceneObjects) { assetGatherer.GatherAssetUuids(sceneObject, assetUuids); } } // Make sure that we also request terrain texture assets RegionSettings regionSettings = m_scene.RegionInfo.RegionSettings; if (m_storeAssets) { if (regionSettings.TerrainTexture1 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_1) { assetUuids[regionSettings.TerrainTexture1] = 1; } if (regionSettings.TerrainTexture2 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_2) { assetUuids[regionSettings.TerrainTexture2] = 1; } if (regionSettings.TerrainTexture3 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_3) { assetUuids[regionSettings.TerrainTexture3] = 1; } if (regionSettings.TerrainTexture4 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_4) { assetUuids[regionSettings.TerrainTexture4] = 1; } } if (MustCheckCreatorIds) { int originalCount = assetUuids.Count; m_log.DebugFormat( "[ARCHIVER]: Filtering {0} asset IDs for {1} allowed creators", originalCount, m_allowedCreatorIds.Count); C5.HashSet <UUID> assetsCreatedByAllowedUsers = this.CollectCreatedAssetIdsFromUserInventories(); IEnumerable <UUID> uuids = new List <UUID>(assetUuids.Keys); assetUuids.Clear(); foreach (UUID assetId in uuids) { if (assetsCreatedByAllowedUsers.Contains(assetId)) { assetUuids.Add(assetId, 1); } } m_log.DebugFormat( "[ARCHIVER]: Allowing export of {0} of {1} assets", assetUuids.Count, originalCount); } m_log.DebugFormat( "[ARCHIVER]: {0} scene objects to serialize requiring save of {1} assets", sceneObjects.Count, assetUuids.Count); TarArchiveWriter archiveWriter = new TarArchiveWriter(m_saveStream); // Asynchronously request all the assets required to perform this archive operation ArchiveWriteRequestExecution awre = new ArchiveWriteRequestExecution( sceneObjects, m_scene.RequestModuleInterface <ITerrainModule>(), m_scene.RequestModuleInterface <IRegionSerializerModule>(), m_scene, archiveWriter, m_requestId); // Write out archive.xml control file first archiveWriter.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, awre.CreateControlFile(assetUuids.Count > 0)); m_log.InfoFormat("[ARCHIVER]: Added {0} control file to archive.", ArchiveConstants.CONTROL_FILE_PATH); // Now include the user list file (only if assets are being saved and it produced a list). if (userlist.Count > 0) { StringBuilder sb = new StringBuilder(); foreach (UUID id in userlist) { String name = m_scene.CommsManager.UserService.Key2Name(id, false); if (!String.IsNullOrWhiteSpace(name)) { sb.AppendFormat("{0} {1}{2}", id, name, Environment.NewLine); } } String userlistContents = sb.ToString(); if (!String.IsNullOrWhiteSpace(userlistContents)) { archiveWriter.WriteFile(ArchiveConstants.USERLIST_FILE_PATH, userlistContents); m_log.InfoFormat("[ARCHIVER]: Added {0} file to archive.", ArchiveConstants.USERLIST_FILE_PATH); } } new AssetsRequest( new AssetsArchiver(archiveWriter, m_scene), assetUuids.Keys, m_scene.CommsManager.AssetCache, awre.ReceivedAllAssets).Execute(); }
public void TestLoadIarV0_1ExistingUsers() { TestHelper.InMethod(); //log4net.Config.XmlConfigurator.Configure(); string userFirstName = "Mr"; string userLastName = "Tiddles"; UUID userUuid = UUID.Parse("00000000-0000-0000-0000-000000000555"); string userItemCreatorFirstName = "Lord"; string userItemCreatorLastName = "Lucan"; UUID userItemCreatorUuid = UUID.Parse("00000000-0000-0000-0000-000000000666"); string item1Name = "b.lsl"; string archiveItemName = InventoryArchiveWriteRequest.CreateArchiveItemName(item1Name, UUID.Random()); MemoryStream archiveWriteStream = new MemoryStream(); TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream); InventoryItemBase item1 = new InventoryItemBase(); item1.Name = item1Name; item1.AssetID = UUID.Random(); item1.GroupID = UUID.Random(); item1.CreatorId = OspResolver.MakeOspa(userItemCreatorFirstName, userItemCreatorLastName); //item1.CreatorId = userUuid.ToString(); //item1.CreatorId = "00000000-0000-0000-0000-000000000444"; item1.Owner = UUID.Zero; string item1FileName = string.Format("{0}{1}", ArchiveConstants.INVENTORY_PATH, archiveItemName); tar.WriteFile(item1FileName, UserInventoryItemSerializer.Serialize(item1)); tar.Close(); MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray()); SerialiserModule serialiserModule = new SerialiserModule(); InventoryArchiverModule archiverModule = new InventoryArchiverModule(true); // Annoyingly, we have to set up a scene even though inventory loading has nothing to do with a scene Scene scene = SceneSetupHelpers.SetupScene("inventory"); SceneSetupHelpers.SetupSceneModules(scene, serialiserModule, archiverModule); UserProfileTestUtils.CreateUserWithInventory( scene, userFirstName, userLastName, userUuid, "meowfood"); UserProfileTestUtils.CreateUserWithInventory( scene, userItemCreatorFirstName, userItemCreatorLastName, userItemCreatorUuid, "hampshire"); archiverModule.DearchiveInventory(userFirstName, userLastName, "/", "meowfood", archiveReadStream); InventoryItemBase foundItem1 = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, userUuid, item1Name); Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1"); // We have to disable this check since loaded items that did find users via OSPA resolution are now only storing the // UUID, not the OSPA itself. // Assert.That( // foundItem1.CreatorId, Is.EqualTo(item1.CreatorId), // "Loaded item non-uuid creator doesn't match original"); Assert.That( foundItem1.CreatorId, Is.EqualTo(userItemCreatorUuid.ToString()), "Loaded item non-uuid creator doesn't match original"); Assert.That( foundItem1.CreatorIdAsUuid, Is.EqualTo(userItemCreatorUuid), "Loaded item uuid creator doesn't match original"); Assert.That(foundItem1.Owner, Is.EqualTo(userUuid), "Loaded item owner doesn't match inventory reciever"); // Now try loading to a root child folder UserInventoryTestUtils.CreateInventoryFolder(scene.InventoryService, userUuid, "xA"); archiveReadStream = new MemoryStream(archiveReadStream.ToArray()); archiverModule.DearchiveInventory(userFirstName, userLastName, "xA", "meowfood", archiveReadStream); InventoryItemBase foundItem2 = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, userUuid, "xA/" + item1Name); Assert.That(foundItem2, Is.Not.Null, "Didn't find loaded item 2"); // Now try loading to a more deeply nested folder UserInventoryTestUtils.CreateInventoryFolder(scene.InventoryService, userUuid, "xB/xC"); archiveReadStream = new MemoryStream(archiveReadStream.ToArray()); archiverModule.DearchiveInventory(userFirstName, userLastName, "xB/xC", "meowfood", archiveReadStream); InventoryItemBase foundItem3 = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, userUuid, "xB/xC/" + item1Name); Assert.That(foundItem3, Is.Not.Null, "Didn't find loaded item 3"); }
public static void Save( SceneInterface scene, SaveOptions options, Stream outputFile, TTY console_io = null) { using (var gzip = new GZipStream(outputFile, CompressionMode.Compress)) { var writer = new TarArchiveWriter(gzip); bool saveAssets = (options & SaveOptions.NoAssets) == 0; var xmloptions = XmlSerializationOptions.None; if ((options & SaveOptions.Publish) == 0) { xmloptions |= XmlSerializationOptions.WriteOwnerInfo; } if (console_io != null) { console_io.Write("Saving archive info..."); } writer.WriteFile("archive.xml", WriteArchiveXml08(scene, saveAssets)); var objectAssets = new Dictionary <string, AssetData>(); if (console_io != null) { console_io.Write("Collecting object data..."); } foreach (ObjectGroup sog in scene.Objects) { if (sog.IsTemporary || sog.IsAttached) { /* skip temporary or attached */ continue; } AssetData data = sog.Asset(xmloptions | XmlSerializationOptions.WriteXml2 | XmlSerializationOptions.WriteKeyframeMotion | XmlSerializationOptions.WriteRezDate); objectAssets.Add(EscapingMethods.EscapeName(sog.Name) + "_" + ((int)sog.GlobalPosition.X).ToString() + "-" + ((int)sog.GlobalPosition.Y).ToString() + "-" + ((int)sog.GlobalPosition.Z).ToString() + "__" + sog.ID.ToString() + ".xml", data); } #region Save Assets if (saveAssets) { if (console_io != null) { console_io.Write("Saving asset data..."); } /* we only parse sim details when saving assets */ var assetIDs = new List <UUID>(); AssetData data; foreach (AssetData objdata in objectAssets.Values) { foreach (UUID id in objdata.References) { if (id != UUID.Zero && !assetIDs.Contains(id)) { assetIDs.Add(id); } } } foreach (ParcelInfo pinfo in scene.Parcels) { if (pinfo.MediaID != UUID.Zero) { assetIDs.Add(pinfo.MediaID); } if (pinfo.SnapshotID != UUID.Zero) { assetIDs.Add(pinfo.SnapshotID); } } int assetidx = 0; while (assetidx < assetIDs.Count) { UUID assetID = assetIDs[assetidx++]; try { data = scene.AssetService[assetID]; } catch { continue; } writer.WriteAsset(data); try { foreach (UUID refid in data.References) { if (!assetIDs.Contains(refid)) { assetIDs.Add(refid); } } } catch { console_io.WriteFormatted("Failed to parse asset {0}", assetID); } } } #endregion #region Region Settings if (console_io != null) { console_io.Write("Saving region settings..."); } using (var ms = new MemoryStream()) { using (XmlTextWriter xmlwriter = ms.UTF8XmlTextWriter()) { RegionSettings settings = scene.RegionSettings; xmlwriter.WriteStartElement("RegionSettings"); { xmlwriter.WriteStartElement("General"); { xmlwriter.WriteNamedValue("AllowDamage", settings.AllowDamage); xmlwriter.WriteNamedValue("AllowLandResell", settings.AllowLandResell); xmlwriter.WriteNamedValue("AllowLandJoinDivide", settings.AllowLandJoinDivide); xmlwriter.WriteNamedValue("BlockFly", settings.BlockFly); xmlwriter.WriteNamedValue("BlockFlyOver", settings.BlockFlyOver); xmlwriter.WriteNamedValue("BlockLandShowInSearch", settings.BlockShowInSearch); xmlwriter.WriteNamedValue("BlockTerraform", settings.BlockTerraform); xmlwriter.WriteNamedValue("DisableCollisions", settings.DisableCollisions); xmlwriter.WriteNamedValue("DisablePhysics", settings.DisablePhysics); xmlwriter.WriteNamedValue("DisableScripts", settings.DisableScripts); switch (scene.Access) { case RegionAccess.PG: xmlwriter.WriteNamedValue("MaturityRating", 0); break; case RegionAccess.Mature: xmlwriter.WriteNamedValue("MaturityRating", 1); break; case RegionAccess.Adult: default: xmlwriter.WriteNamedValue("MaturityRating", 2); break; } xmlwriter.WriteNamedValue("RestrictPushing", settings.RestrictPushing); xmlwriter.WriteNamedValue("AgentLimit", settings.AgentLimit); xmlwriter.WriteNamedValue("ObjectBonus", settings.ObjectBonus); xmlwriter.WriteNamedValue("ResetHomeOnTeleport", settings.ResetHomeOnTeleport); xmlwriter.WriteNamedValue("AllowLandmark", settings.AllowLandmark); xmlwriter.WriteNamedValue("AllowDirectTeleport", settings.AllowDirectTeleport); xmlwriter.WriteNamedValue("MaxBasePrims", settings.MaxBasePrims); } xmlwriter.WriteEndElement(); xmlwriter.WriteStartElement("GroundTextures"); { xmlwriter.WriteNamedValue("Texture1", settings.TerrainTexture1); xmlwriter.WriteNamedValue("Texture2", settings.TerrainTexture2); xmlwriter.WriteNamedValue("Texture3", settings.TerrainTexture3); xmlwriter.WriteNamedValue("Texture4", settings.TerrainTexture4); xmlwriter.WriteNamedValue("ElevationLowSW", settings.Elevation1SW); xmlwriter.WriteNamedValue("ElevationLowNW", settings.Elevation1NW); xmlwriter.WriteNamedValue("ElevationLowSE", settings.Elevation1SE); xmlwriter.WriteNamedValue("ElevationLowNE", settings.Elevation1NE); xmlwriter.WriteNamedValue("ElevationHighSW", settings.Elevation2SW); xmlwriter.WriteNamedValue("ElevationHighNW", settings.Elevation2NW); xmlwriter.WriteNamedValue("ElevationHighSE", settings.Elevation2SE); xmlwriter.WriteNamedValue("ElevationHighNE", settings.Elevation2NE); } xmlwriter.WriteEndElement(); xmlwriter.WriteStartElement("Terrain"); { xmlwriter.WriteNamedValue("WaterHeight", settings.WaterHeight); xmlwriter.WriteNamedValue("TerrainRaiseLimit", settings.TerrainRaiseLimit); xmlwriter.WriteNamedValue("TerrainLowerLimit", settings.TerrainLowerLimit); xmlwriter.WriteNamedValue("UseEstateSun", settings.UseEstateSun); xmlwriter.WriteNamedValue("FixedSun", settings.IsSunFixed); xmlwriter.WriteNamedValue("SunPosition", settings.SunPosition + 6); } xmlwriter.WriteEndElement(); xmlwriter.WriteNamedValue("WalkableCoefficients", Convert.ToBase64String(settings.WalkableCoefficientsSerialization)); if (settings.TelehubObject != UUID.Zero) { xmlwriter.WriteStartElement("Telehub"); { xmlwriter.WriteNamedValue("TelehubObject", settings.TelehubObject); // yes, OpenSim likes to convert around data double yaw; double pitch; double distance; foreach (Vector3 sp in scene.SpawnPoints) { distance = sp.Length; Vector3 dir = sp.Normalize(); // Get the bearing of the spawn point yaw = (float)Math.Atan2(dir.Y, dir.X); // Get the elevation of the spawn point pitch = (float)-Math.Atan2(dir.Z, Math.Sqrt(dir.X * dir.X + dir.Y * dir.Y)); xmlwriter.WriteNamedValue("SpawnPoint", string.Format(CultureInfo.InvariantCulture, "{0},{1},{2}", yaw, pitch, distance)); } } xmlwriter.WriteEndElement(); } } xmlwriter.WriteEndElement(); } writer.WriteFile("settings/" + scene.Name + ".xml", ms.ToArray()); } #endregion #region Saving parcels if (console_io != null) { console_io.Write("Saving parcel data..."); } foreach (ParcelInfo pinfo in scene.Parcels) { using (var ms = new MemoryStream()) { using (XmlTextWriter xmlwriter = ms.UTF8XmlTextWriter()) { xmlwriter.WriteStartElement("LandData"); { xmlwriter.WriteNamedValue("Area", pinfo.Area); xmlwriter.WriteNamedValue("AuctionID", pinfo.AuctionID); xmlwriter.WriteNamedValue("AuthBuyerID", pinfo.AuthBuyer.ID); xmlwriter.WriteNamedValue("Category", (byte)pinfo.Category); xmlwriter.WriteNamedValue("ClaimDate", pinfo.ClaimDate.DateTimeToUnixTime().ToString()); xmlwriter.WriteNamedValue("ClaimPrice", pinfo.ClaimPrice); xmlwriter.WriteNamedValue("GlobalID", pinfo.ID); if ((options & SaveOptions.Publish) != 0) { xmlwriter.WriteNamedValue("GroupID", UUID.Zero); xmlwriter.WriteNamedValue("IsGroupOwned", false); } else { xmlwriter.WriteNamedValue("GroupID", pinfo.Group.ID); xmlwriter.WriteNamedValue("IsGroupOwned", pinfo.GroupOwned); } xmlwriter.WriteNamedValue("Bitmap", Convert.ToBase64String(pinfo.LandBitmap.Data)); xmlwriter.WriteNamedValue("Description", pinfo.Description); xmlwriter.WriteNamedValue("Flags", (uint)pinfo.Flags); xmlwriter.WriteNamedValue("LandingType", (uint)pinfo.LandingType); xmlwriter.WriteNamedValue("Name", pinfo.Name); xmlwriter.WriteNamedValue("Status", (uint)pinfo.Status); xmlwriter.WriteNamedValue("LocalID", pinfo.LocalID); xmlwriter.WriteNamedValue("MediaAutoScale", pinfo.MediaAutoScale); xmlwriter.WriteNamedValue("MediaID", pinfo.MediaID); if (pinfo.MediaURI != null) { xmlwriter.WriteNamedValue("MediaURL", pinfo.MediaURI.ToString()); } else { xmlwriter.WriteStartElement("MediaURL"); xmlwriter.WriteEndElement(); } if (pinfo.MusicURI != null) { xmlwriter.WriteNamedValue("MusicURL", pinfo.MusicURI.ToString()); } else { xmlwriter.WriteStartElement("MusicURL"); xmlwriter.WriteEndElement(); } xmlwriter.WriteNamedValue("OwnerID", pinfo.Owner.ID); xmlwriter.WriteStartElement("ParcelAccessList"); if ((options & SaveOptions.Publish) == 0) { /* only serialize ParcelAccessEntry when not writing Publish OAR */ foreach (ParcelAccessEntry pae in scene.Parcels.WhiteList[scene.ID, pinfo.ID]) { xmlwriter.WriteStartElement("ParcelAccessEntry"); xmlwriter.WriteNamedValue("AgentID", pae.Accessor.ID.ToString()); xmlwriter.WriteNamedValue("AgentData", pae.Accessor.CreatorData); xmlwriter.WriteNamedValue("Time", pae.ExpiresAt.AsULong); xmlwriter.WriteNamedValue("AccessList", (int)OarAccessFlags.Access); xmlwriter.WriteEndElement(); } foreach (ParcelAccessEntry pae in scene.Parcels.BlackList[scene.ID, pinfo.ID]) { xmlwriter.WriteStartElement("ParcelAccessEntry"); xmlwriter.WriteNamedValue("AgentID", pae.Accessor.ID.ToString()); xmlwriter.WriteNamedValue("AgentData", pae.Accessor.CreatorData); xmlwriter.WriteNamedValue("Time", pae.ExpiresAt.AsULong); xmlwriter.WriteNamedValue("AccessList", (int)OarAccessFlags.Ban); xmlwriter.WriteEndElement(); } } xmlwriter.WriteEndElement(); xmlwriter.WriteNamedValue("PassHours", pinfo.PassHours); xmlwriter.WriteNamedValue("PassPrice", pinfo.PassPrice); xmlwriter.WriteNamedValue("SalePrice", pinfo.SalePrice); xmlwriter.WriteNamedValue("SnapshotID", pinfo.SnapshotID); xmlwriter.WriteNamedValue("UserLocation", pinfo.LandingPosition.ToString()); xmlwriter.WriteNamedValue("UserLookAt", pinfo.LandingLookAt.ToString()); xmlwriter.WriteNamedValue("Dwell", pinfo.Dwell); xmlwriter.WriteNamedValue("OtherCleanTime", pinfo.OtherCleanTime); } xmlwriter.WriteEndElement(); xmlwriter.Flush(); writer.WriteFile("landdata/" + pinfo.ID.ToString() + ".xml", ms.ToArray()); } } } #endregion #region Storing object data if (console_io != null) { console_io.Write("Storing object data..."); } foreach (KeyValuePair <string, AssetData> kvp in objectAssets) { writer.WriteFile("objects/" + kvp.Key, kvp.Value.Data); } #endregion #region Storing terrain if (console_io != null) { console_io.Write("Saving terrain data..."); } writer.WriteFile("terrains/" + scene.Name + ".r32", GenTerrainFile(scene.Terrain.AllPatches)); #endregion writer.WriteEndOfTar(); } }
/// <summary> /// Archive the region requested. /// </summary> /// <exception cref="System.IO.IOException">if there was an io problem with creating the file</exception> public void ArchiveRegion(Dictionary <string, object> options) { Dictionary <UUID, AssetType> assetUuids = new Dictionary <UUID, AssetType>(); EntityBase[] entities = m_scene.GetEntities(); List <SceneObjectGroup> sceneObjects = new List <SceneObjectGroup>(); /* * foreach (ILandObject lo in m_scene.LandChannel.AllParcels()) * { * if (name == lo.LandData.Name) * { * // This is the parcel we want * } * } */ // Filter entities so that we only have scene objects. // FIXME: Would be nicer to have this as a proper list in SceneGraph, since lots of methods // end up having to do this foreach (EntityBase entity in entities) { if (entity is SceneObjectGroup) { SceneObjectGroup sceneObject = (SceneObjectGroup)entity; if (!sceneObject.IsDeleted && !sceneObject.IsAttachment) { sceneObjects.Add((SceneObjectGroup)entity); } } } UuidGatherer assetGatherer = new UuidGatherer(m_scene.AssetService); foreach (SceneObjectGroup sceneObject in sceneObjects) { assetGatherer.GatherAssetUuids(sceneObject, assetUuids); } m_log.DebugFormat( "[ARCHIVER]: {0} scene objects to serialize requiring save of {1} assets", sceneObjects.Count, assetUuids.Count); // Make sure that we also request terrain texture assets RegionSettings regionSettings = m_scene.RegionInfo.RegionSettings; if (regionSettings.TerrainTexture1 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_1) { assetUuids[regionSettings.TerrainTexture1] = AssetType.Texture; } if (regionSettings.TerrainTexture2 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_2) { assetUuids[regionSettings.TerrainTexture2] = AssetType.Texture; } if (regionSettings.TerrainTexture3 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_3) { assetUuids[regionSettings.TerrainTexture3] = AssetType.Texture; } if (regionSettings.TerrainTexture4 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_4) { assetUuids[regionSettings.TerrainTexture4] = AssetType.Texture; } TarArchiveWriter archiveWriter = new TarArchiveWriter(m_saveStream); // Asynchronously request all the assets required to perform this archive operation ArchiveWriteRequestExecution awre = new ArchiveWriteRequestExecution( sceneObjects, m_scene.RequestModuleInterface <IVoxelModule>(), m_scene.RequestModuleInterface <IRegionSerialiserModule>(), m_scene, archiveWriter, m_requestId, options); m_log.InfoFormat("[ARCHIVER]: Creating archive file. This may take some time."); // Write out control file. This has to be done first so that subsequent loaders will see this file first // XXX: I know this is a weak way of doing it since external non-OAR aware tar executables will not do this archiveWriter.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, Create0p2ControlFile(options)); m_log.InfoFormat("[ARCHIVER]: Added control file to archive."); new AssetsRequest( new AssetsArchiver(archiveWriter), assetUuids, m_scene.AssetService, awre.ReceivedAllAssets).Execute(); }
public void SaveModuleToArchive(TarArchiveWriter writer, IScene scene) { m_isArchiving = true; MainConsole.Instance.Info("[Archive]: Writing parcels to archive"); writer.WriteDir("parcels"); IParcelManagementModule module = scene.RequestModuleInterface <IParcelManagementModule>(); if (module != null) { List <ILandObject> landObject = module.AllParcels(); foreach (ILandObject parcel in landObject) { OSDMap parcelMap = parcel.LandData.ToOSD(); writer.WriteFile("parcels/" + parcel.LandData.GlobalID.ToString(), OSDParser.SerializeLLSDBinary(parcelMap)); parcelMap = null; } } MainConsole.Instance.Info("[Archive]: Finished writing parcels to archive"); MainConsole.Instance.Info("[Archive]: Writing terrain to archive"); writer.WriteDir("newstyleterrain"); writer.WriteDir("newstylerevertterrain"); writer.WriteDir("newstylewater"); writer.WriteDir("newstylerevertwater"); ITerrainModule tModule = scene.RequestModuleInterface <ITerrainModule>(); if (tModule != null) { try { byte[] sdata = WriteTerrainToStream(tModule.TerrainMap); writer.WriteFile("newstyleterrain/" + scene.RegionInfo.RegionID + ".terrain", sdata); sdata = WriteTerrainToStream(tModule.TerrainRevertMap); writer.WriteFile("newstylerevertterrain/" + scene.RegionInfo.RegionID + ".terrain", sdata); sdata = null; if (tModule.TerrainWaterMap != null) { sdata = WriteTerrainToStream(tModule.TerrainWaterMap); writer.WriteFile("newstylewater/" + scene.RegionInfo.RegionID + ".terrain", sdata); sdata = null; sdata = WriteTerrainToStream(tModule.TerrainWaterRevertMap); writer.WriteFile( "newstylerevertwater/" + scene.RegionInfo.RegionID + ".terrain", sdata); sdata = null; } } catch (Exception ex) { MainConsole.Instance.WarnFormat("[Backup]: Exception caught: {0}", ex); } } MainConsole.Instance.Info("[Archive]: Finished writing terrain to archive"); MainConsole.Instance.Info("[Archive]: Writing entities to archive"); ISceneEntity[] entities = scene.Entities.GetEntities(); //Get all entities, then start writing them to the database writer.WriteDir("entities"); IDictionary <UUID, AssetType> assets = new Dictionary <UUID, AssetType>(); UuidGatherer assetGatherer = new UuidGatherer(m_scene.AssetService); IWhiteCoreBackupArchiver archiver = m_scene.RequestModuleInterface <IWhiteCoreBackupArchiver>(); bool saveAssets = false; if (archiver.AllowPrompting) { saveAssets = MainConsole.Instance.Prompt("Save assets? (Will not be able to load on other grids if not saved)", "false") .Equals("true", StringComparison.CurrentCultureIgnoreCase); } int count = 0; foreach (ISceneEntity entity in entities) { try { if (entity.IsAttachment || ((entity.RootChild.Flags & PrimFlags.Temporary) == PrimFlags.Temporary) || ((entity.RootChild.Flags & PrimFlags.TemporaryOnRez) == PrimFlags.TemporaryOnRez)) { continue; } //Write all entities byte[] xml = entity.ToBinaryXml2(); writer.WriteFile("entities/" + entity.UUID, xml); xml = null; count++; if (count % 3 == 0) { Thread.Sleep(5); } //Get all the assets too if (saveAssets) { assetGatherer.GatherAssetUuids(entity, assets); } } catch (Exception ex) { MainConsole.Instance.WarnFormat("[Backup]: Exception caught: {0}", ex); } } entities = null; MainConsole.Instance.Info("[Archive]: Finished writing entities to archive"); MainConsole.Instance.Info("[Archive]: Writing assets for entities to archive"); bool foundAllAssets = true; foreach (UUID assetID in new List <UUID>(assets.Keys)) { try { foundAllAssets = false; //Not all are cached m_scene.AssetService.Get(assetID.ToString(), writer, RetrievedAsset); m_missingAssets.Add(assetID); } catch (Exception ex) { MainConsole.Instance.WarnFormat("[Backup]: Exception caught: {0}", ex); } } if (foundAllAssets) { m_isArchiving = false; //We're done if all the assets were found } MainConsole.Instance.Info("[Archive]: Finished writing assets for entities to archive"); }
/// <summary> /// Execute the inventory write request /// </summary> public void Execute() { InventoryFolderImpl inventoryFolder = null; InventoryItemBase inventoryItem = null; if (!m_userInfo.HasReceivedInventory) { // If the region server has access to the user admin service (by which users are created), // then we'll assume that it's okay to fiddle with the user's inventory even if they are not on the // server. // // FIXME: FetchInventory should probably be assumed to by async anyway, since even standalones might // use a remote inventory service, though this is vanishingly rare at the moment. if (null == m_module.CommsManager.UserAdminService) { m_log.ErrorFormat( "[INVENTORY ARCHIVER]: Have not yet received inventory info for user {0} {1}", m_userInfo.UserProfile.Name, m_userInfo.UserProfile.ID); return; } else { m_userInfo.FetchInventory(); } } bool foundStar = false; // Eliminate double slashes and any leading / on the path. This might be better done within InventoryFolderImpl // itself (possibly at a small loss in efficiency). string[] components = m_invPath.Split(new string[] { InventoryFolderImpl.PATH_DELIMITER }, StringSplitOptions.RemoveEmptyEntries); int maxComponentIndex = components.Length - 1; // If the path terminates with a STAR then later on we want to archive all nodes in the folder but not the // folder itself. This may get more sophisicated later on if (maxComponentIndex >= 0 && components[maxComponentIndex] == STAR_WILDCARD) { foundStar = true; maxComponentIndex--; } m_invPath = String.Empty; for (int i = 0; i <= maxComponentIndex; i++) { m_invPath += components[i] + InventoryFolderImpl.PATH_DELIMITER; } // Annoyingly Split actually returns the original string if the input string consists only of delimiters // Therefore if we still start with a / after the split, then we need the root folder if (m_invPath.Length == 0) { inventoryFolder = m_userInfo.RootFolder; } else { m_invPath = m_invPath.Remove(m_invPath.LastIndexOf(InventoryFolderImpl.PATH_DELIMITER)); inventoryFolder = m_userInfo.RootFolder.FindFolderByPath(m_invPath); } // The path may point to an item instead if (inventoryFolder == null) { inventoryItem = m_userInfo.RootFolder.FindItemByPath(m_invPath); } m_archiveWriter = new TarArchiveWriter(m_saveStream); if (null == inventoryFolder) { if (null == inventoryItem) { // We couldn't find the path indicated m_saveStream.Close(); m_module.TriggerInventoryArchiveSaved( false, m_userInfo, m_invPath, m_saveStream, new Exception(string.Format("Could not find inventory entry at path {0}", m_invPath))); return; } else { m_log.DebugFormat( "[INVENTORY ARCHIVER]: Found item {0} {1} at {2}", inventoryItem.Name, inventoryItem.ID, m_invPath); SaveInvItem(inventoryItem, ArchiveConstants.INVENTORY_PATH); } } else { m_log.DebugFormat( "[INVENTORY ARCHIVER]: Found folder {0} {1} at {2}", inventoryFolder.Name, inventoryFolder.ID, m_invPath); //recurse through all dirs getting dirs and files SaveInvFolder(inventoryFolder, ArchiveConstants.INVENTORY_PATH, !foundStar); } SaveUsers(); new AssetsRequest( new AssetsArchiver(m_archiveWriter), m_assetUuids.Keys, m_module.AssetService, ReceivedAllAssets).Execute(); }
/// <summary> /// Execute the inventory write request /// </summary> public void Execute(Dictionary <string, object> options, IUserAccountService userAccountService) { if (options.ContainsKey("noassets") && (bool)options["noassets"]) { SaveAssets = false; } try { InventoryFolderBase inventoryFolder = null; InventoryItemBase inventoryItem = null; InventoryFolderBase rootFolder = m_scene.InventoryService.GetRootFolder(m_userInfo.PrincipalID); bool saveFolderContentsOnly = false; // Eliminate double slashes and any leading / on the path. string[] components = m_invPath.Split( new string[] { InventoryFolderImpl.PATH_DELIMITER }, StringSplitOptions.RemoveEmptyEntries); int maxComponentIndex = components.Length - 1; // If the path terminates with a STAR then later on we want to archive all nodes in the folder but not the // folder itself. This may get more sophisicated later on if (maxComponentIndex >= 0 && components[maxComponentIndex] == STAR_WILDCARD) { saveFolderContentsOnly = true; maxComponentIndex--; } else if (maxComponentIndex == -1) { // If the user has just specified "/", then don't save the root "My Inventory" folder. This is // more intuitive then requiring the user to specify "/*" for this. saveFolderContentsOnly = true; } m_invPath = String.Empty; for (int i = 0; i <= maxComponentIndex; i++) { m_invPath += components[i] + InventoryFolderImpl.PATH_DELIMITER; } // Annoyingly Split actually returns the original string if the input string consists only of delimiters // Therefore if we still start with a / after the split, then we need the root folder if (m_invPath.Length == 0) { inventoryFolder = rootFolder; } else { m_invPath = m_invPath.Remove(m_invPath.LastIndexOf(InventoryFolderImpl.PATH_DELIMITER)); List <InventoryFolderBase> candidateFolders = InventoryArchiveUtils.FindFoldersByPath(m_scene.InventoryService, rootFolder, m_invPath); if (candidateFolders.Count > 0) { inventoryFolder = candidateFolders[0]; } } // The path may point to an item instead if (inventoryFolder == null) { inventoryItem = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, rootFolder, m_invPath); } if (null == inventoryFolder && null == inventoryItem) { // We couldn't find the path indicated string errorMessage = string.Format("Aborted save. Could not find inventory path {0}", m_invPath); Exception e = new InventoryArchiverException(errorMessage); m_module.TriggerInventoryArchiveSaved(m_id, false, m_userInfo, m_invPath, m_saveStream, e); throw e; } m_archiveWriter = new TarArchiveWriter(m_saveStream); m_log.InfoFormat("[INVENTORY ARCHIVER]: Adding control file to archive."); // Write out control file. This has to be done first so that subsequent loaders will see this file first // XXX: I know this is a weak way of doing it since external non-OAR aware tar executables will not do this // not sure how to fix this though, short of going with a completely different file format. m_archiveWriter.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, CreateControlFile(options)); if (inventoryFolder != null) { m_log.DebugFormat( "[INVENTORY ARCHIVER]: Found folder {0} {1} at {2}", inventoryFolder.Name, inventoryFolder.ID, m_invPath == String.Empty ? InventoryFolderImpl.PATH_DELIMITER : m_invPath); //recurse through all dirs getting dirs and files SaveInvFolder(inventoryFolder, ArchiveConstants.INVENTORY_PATH, !saveFolderContentsOnly, options, userAccountService); } else if (inventoryItem != null) { m_log.DebugFormat( "[INVENTORY ARCHIVER]: Found item {0} {1} at {2}", inventoryItem.Name, inventoryItem.ID, m_invPath); SaveInvItem(inventoryItem, ArchiveConstants.INVENTORY_PATH, options, userAccountService); } // Don't put all this profile information into the archive right now. //SaveUsers(); if (SaveAssets) { m_log.DebugFormat("[INVENTORY ARCHIVER]: Saving {0} assets for items", m_assetUuids.Count); AssetsRequest ar = new AssetsRequest( new AssetsArchiver(m_archiveWriter), m_assetUuids, m_scene.AssetService, m_scene.UserAccountService, m_scene.RegionInfo.ScopeID, options, ReceivedAllAssets); Util.RunThreadNoTimeout(o => ar.Execute(), "AssetsRequest", null); } else { m_log.DebugFormat("[INVENTORY ARCHIVER]: Not saving assets since --noassets was specified"); ReceivedAllAssets(new List <UUID>(), new List <UUID>(), false); } } catch (Exception) { m_saveStream.Close(); throw; } }
public AssetsArchiver(TarArchiveWriter archiveWriter) { m_archiveWriter = archiveWriter; }
public bool SaveBackup(string fileName, RegionData regiondata) { try { bool oldFileExists = File.Exists(fileName); //Do new style saving here! GZipStream m_saveStream = new GZipStream(new FileStream(fileName + ".tmp", FileMode.Create), CompressionMode.Compress); TarArchiveWriter writer = new TarArchiveWriter(m_saveStream); GZipStream m_loadStream = new GZipStream(new FileStream(fileName, FileMode.Open), CompressionMode.Decompress); TarArchiveReader reader = new TarArchiveReader(m_loadStream); writer.WriteDir("parcels"); foreach (LandData parcel in regiondata.Parcels) { OSDMap parcelMap = parcel.ToOSD(); var binary = OSDParser.SerializeLLSDBinary(parcelMap); writer.WriteFile("parcels/" + parcel.GlobalID.ToString(), binary); binary = null; parcelMap = null; } writer.WriteDir("newstyleterrain"); writer.WriteDir("newstylerevertterrain"); writer.WriteDir("newstylewater"); writer.WriteDir("newstylerevertwater"); writer.WriteDir("regioninfo"); byte[] regionData = OSDParser.SerializeLLSDBinary(regiondata.RegionInfo.PackRegionInfoData()); writer.WriteFile("regioninfo/regioninfo", regionData); try { writer.WriteFile("newstyleterrain/" + regiondata.RegionInfo.RegionID.ToString() + ".terrain", regiondata.Terrain); writer.WriteFile( "newstylerevertterrain/" + regiondata.RegionInfo.RegionID.ToString() + ".terrain", regiondata.RevertTerrain); if (regiondata.Water != null) { writer.WriteFile("newstylewater/" + regiondata.RegionInfo.RegionID.ToString() + ".terrain", regiondata.Water); writer.WriteFile( "newstylerevertwater/" + regiondata.RegionInfo.RegionID.ToString() + ".terrain", regiondata.RevertWater); } } catch (Exception ex) { MainConsole.Instance.WarnFormat("[Backup]: Exception caught: {0}", ex); } List <UUID> entitiesToSave = new List <UUID>(); foreach (ISceneEntity entity in regiondata.Groups) { try { if (entity.IsAttachment || ((entity.RootChild.Flags & PrimFlags.Temporary) == PrimFlags.Temporary) || ((entity.RootChild.Flags & PrimFlags.TemporaryOnRez) == PrimFlags.TemporaryOnRez)) { continue; } if (entity.HasGroupChanged || !oldFileExists) { entity.HasGroupChanged = false; //Write all entities writer.WriteFile("entities/" + entity.UUID.ToString(), entity.ToBinaryXml2()); } else { entitiesToSave.Add(entity.UUID); } } catch (Exception ex) { MainConsole.Instance.WarnFormat("[Backup]: Exception caught: {0}", ex); entitiesToSave.Add(entity.UUID); } } if (oldFileExists) { byte[] data; string filePath; TarArchiveReader.TarEntryType entryType; //Load the archive data that we need try { while ((data = reader.ReadEntry(out filePath, out entryType)) != null) { if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType) { continue; } if (filePath.StartsWith("entities/")) { UUID entityID = UUID.Parse(filePath.Remove(0, 9)); if (entitiesToSave.Contains(entityID)) { writer.WriteFile(filePath, data); entitiesToSave.Remove(entityID); } } data = null; } } catch (Exception ex) { MainConsole.Instance.WarnFormat("[Backup]: Exception caught: {0}", ex); } if (entitiesToSave.Count > 0) { MainConsole.Instance.Fatal(entitiesToSave.Count + " PRIMS WERE NOT GOING TO BE SAVED! FORCE SAVING NOW! "); foreach (ISceneEntity entity in regiondata.Groups) { if (entitiesToSave.Contains(entity.UUID)) { if (entity.IsAttachment || ((entity.RootChild.Flags & PrimFlags.Temporary) == PrimFlags.Temporary) || ((entity.RootChild.Flags & PrimFlags.TemporaryOnRez) == PrimFlags.TemporaryOnRez)) { continue; } //Write all entities byte[] xml = entity.ToBinaryXml2(); writer.WriteFile("entities/" + entity.UUID.ToString(), xml); xml = null; } } } } reader.Close(); writer.Close(); m_loadStream.Close(); m_saveStream.Close(); GC.Collect(); } catch (Exception ex) { MainConsole.Instance.Warn("[ProtobufRegionLoader]: Failed to save backup: " + ex.ToString()); return(false); } return(true); }
/// <summary> /// Archive the region requested. /// </summary> /// <exception cref="System.IO.IOException">if there was an io problem with creating the file</exception> public void ArchiveRegion(Dictionary <string, object> options) { m_options = options; if (options.ContainsKey("all") && (bool)options["all"]) { MultiRegionFormat = true; } if (options.ContainsKey("noassets") && (bool)options["noassets"]) { SaveAssets = false; } Object temp; if (options.TryGetValue("checkPermissions", out temp)) { CheckPermissions = (string)temp; } // Find the regions to archive ArchiveScenesGroup scenesGroup = new ArchiveScenesGroup(); if (MultiRegionFormat) { m_log.InfoFormat("[ARCHIVER]: Saving {0} regions", SceneManager.Instance.Scenes.Count); SceneManager.Instance.ForEachScene(delegate(Scene scene) { scenesGroup.AddScene(scene); }); } else { scenesGroup.AddScene(m_rootScene); } scenesGroup.CalcSceneLocations(); m_archiveWriter = new TarArchiveWriter(m_saveStream); try { // Write out control file. It should be first so that it will be found ASAP when loading the file. m_archiveWriter.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, CreateControlFile(scenesGroup)); m_log.InfoFormat("[ARCHIVER]: Added control file to archive."); // Archive the regions Dictionary <UUID, sbyte> assetUuids = new Dictionary <UUID, sbyte>(); scenesGroup.ForEachScene(delegate(Scene scene) { string regionDir = MultiRegionFormat ? scenesGroup.GetRegionDir(scene.RegionInfo.RegionID) : ""; ArchiveOneRegion(scene, regionDir, assetUuids); }); // Archive the assets if (SaveAssets) { m_log.DebugFormat("[ARCHIVER]: Saving {0} assets", assetUuids.Count); // Asynchronously request all the assets required to perform this archive operation AssetsRequest ar = new AssetsRequest( new AssetsArchiver(m_archiveWriter), assetUuids, m_rootScene.AssetService, m_rootScene.UserAccountService, m_rootScene.RegionInfo.ScopeID, options, ReceivedAllAssets); Util.RunThreadNoTimeout(o => ar.Execute(), "AssetsRequest", null); // CloseArchive() will be called from ReceivedAllAssets() } else { m_log.DebugFormat("[ARCHIVER]: Not saving assets since --noassets was specified"); CloseArchive(string.Empty); } } catch (Exception e) { CloseArchive(e.Message); throw; } }
public void SaveModuleToArchive(TarArchiveWriter writer, IScene scene) { m_isArchiving = true; m_log.Info("[Archive]: Writing parcels to archive"); writer.WriteDir("parcels"); IParcelManagementModule module = scene.RequestModuleInterface <IParcelManagementModule>(); if (module != null) { List <ILandObject> landObject = module.AllParcels(); foreach (ILandObject parcel in landObject) { OSDMap parcelMap = parcel.LandData.ToOSD(); writer.WriteFile("parcels/" + parcel.LandData.GlobalID.ToString(), OSDParser.SerializeLLSDBinary(parcelMap)); } } m_log.Info("[Archive]: Finished writing parcels to archive"); m_log.Info("[Archive]: Writing terrain to archive"); writer.WriteDir("terrain"); ITerrainModule tModule = scene.RequestModuleInterface <ITerrainModule>(); if (tModule != null) { MemoryStream s = new MemoryStream(); tModule.SaveToStream(scene.RegionInfo.RegionID.ToString() + ".r32", s); writer.WriteFile("terrain/" + scene.RegionInfo.RegionID.ToString() + ".r32", s.ToArray()); s.Close(); } m_log.Info("[Archive]: Finished writing terrain to archive"); m_log.Info("[Archive]: Writing entities to archive"); ISceneEntity[] entities = scene.Entities.GetEntities(); //Get all entities, then start writing them to the database writer.WriteDir("entities"); IDictionary <UUID, AssetType> assets = new Dictionary <UUID, AssetType>(); UuidGatherer assetGatherer = new UuidGatherer(m_scene.AssetService); foreach (ISceneEntity entity in entities) { //Write all entities writer.WriteFile("entities/" + entity.UUID.ToString(), ((ISceneObject)entity).ToXml2()); //Get all the assets too assetGatherer.GatherAssetUuids(entity, assets, scene); } m_log.Info("[Archive]: Finished writing entities to archive"); m_log.Info("[Archive]: Writing assets for entities to archive"); bool foundAllAssets = true; foreach (UUID assetID in new List <UUID>(assets.Keys)) { AssetBase asset = m_scene.AssetService.GetCached(assetID.ToString()); if (asset != null) { WriteAsset(asset, writer); //Write it syncronously since we havn't } else { foundAllAssets = false; //Not all are cached m_missingAssets.Add(assetID); m_scene.AssetService.Get(assetID.ToString(), writer, RetrievedAsset); } } if (foundAllAssets) { m_isArchiving = false; //We're done if all the assets were found } m_log.Info("[Archive]: Finished writing assets for entities to archive"); }
public void TestLoadIarV0p1ExistingUsers() { Assert.Ignore(); TestHelper.InMethod(); Console.WriteLine("Started {0}", MethodBase.GetCurrentMethod()); //log4net.Config.XmlConfigurator.Configure(); string userFirstName = "Mr"; string userLastName = "Tiddles"; UUID userUuid = UUID.Parse("00000000-0000-0000-0000-000000000555"); string user2FirstName = "Lord"; string user2LastName = "Lucan"; UUID user2Uuid = UUID.Parse("00000000-0000-0000-0000-000000000666"); string itemName = "b.lsl"; string archiveItemName = string.Format("{0}{1}{2}", itemName, "_", UUID.Random()); MemoryStream archiveWriteStream = new MemoryStream(); TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream); InventoryItemBase item1 = new InventoryItemBase(); item1.Name = itemName; item1.AssetID = UUID.Random(); item1.GroupID = UUID.Random(); item1.CreatorId = OspResolver.MakeOspa(user2FirstName, user2LastName); //item1.CreatorId = userUuid.ToString(); //item1.CreatorId = "00000000-0000-0000-0000-000000000444"; item1.Owner = UUID.Zero; string item1FileName = string.Format("{0}{1}", ArchiveConstants.INVENTORY_PATH, archiveItemName); tar.WriteFile(item1FileName, UserInventoryItemSerializer.Serialize(item1)); tar.Close(); MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray()); SerialiserModule serialiserModule = new SerialiserModule(); InventoryArchiverModule archiverModule = new InventoryArchiverModule(); // Annoyingly, we have to set up a scene even though inventory loading has nothing to do with a scene Scene scene = SceneSetupHelpers.SetupScene(); IUserAdminService userAdminService = scene.CommsManager.UserAdminService; SceneSetupHelpers.SetupSceneModules(scene, serialiserModule, archiverModule); userAdminService.AddUser( userFirstName, userLastName, "meowfood", String.Empty, 1000, 1000, userUuid); userAdminService.AddUser( user2FirstName, user2LastName, "hampshire", String.Empty, 1000, 1000, user2Uuid); archiverModule.DearchiveInventory(userFirstName, userLastName, "/", archiveReadStream); CachedUserInfo userInfo = scene.CommsManager.UserProfileCacheService.GetUserDetails(userFirstName, userLastName); InventoryItemBase foundItem = userInfo.RootFolder.FindItemByPath(itemName); Assert.That(foundItem.CreatorId, Is.EqualTo(item1.CreatorId)); Assert.That(foundItem.CreatorIdAsUuid, Is.EqualTo(user2Uuid)); Assert.That(foundItem.Owner, Is.EqualTo(userUuid)); Console.WriteLine("Successfully completed {0}", MethodBase.GetCurrentMethod()); }
/// <summary> /// Archive the region requested. /// </summary> /// <exception cref="System.IO.IOException">if there was an io problem with creating the file</exception> public void ArchiveRegion(Dictionary <string, object> options) { m_options = options; if (options.ContainsKey("all") && (bool)options["all"]) { MultiRegionFormat = true; } if (options.ContainsKey("noassets") && (bool)options["noassets"]) { SaveAssets = false; } if (options.TryGetValue("checkPermissions", out Object temp)) { FilterContent = (string)temp; } // Find the regions to archive ArchiveScenesGroup scenesGroup = new ArchiveScenesGroup(); if (MultiRegionFormat) { m_log.InfoFormat("[ARCHIVER]: Saving {0} regions", SceneManager.Instance.Scenes.Count); SceneManager.Instance.ForEachScene(delegate(Scene scene) { scenesGroup.AddScene(scene); }); } else { scenesGroup.AddScene(m_rootScene); } scenesGroup.CalcSceneLocations(); m_archiveWriter = new TarArchiveWriter(m_saveStream); try { // Write out control file. It should be first so that it will be found ASAP when loading the file. m_archiveWriter.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, CreateControlFile(scenesGroup)); m_log.InfoFormat("[ARCHIVER]: Added control file to archive."); // Archive the regions Dictionary <UUID, sbyte> assetUuids = new Dictionary <UUID, sbyte>(); HashSet <UUID> failedIDs = new HashSet <UUID>(); HashSet <UUID> uncertainAssetsUUIDs = new HashSet <UUID>(); scenesGroup.ForEachScene(delegate(Scene scene) { string regionDir = MultiRegionFormat ? scenesGroup.GetRegionDir(scene.RegionInfo.RegionID) : ""; ArchiveOneRegion(scene, regionDir, assetUuids, failedIDs, uncertainAssetsUUIDs); }); // Archive the assets if (SaveAssets) { m_log.DebugFormat("[ARCHIVER]: Saving {0} assets", assetUuids.Count); AssetsRequest ar = new AssetsRequest( new AssetsArchiver(m_archiveWriter), assetUuids, failedIDs.Count, m_rootScene.AssetService, m_rootScene.UserAccountService, m_rootScene.RegionInfo.ScopeID, options, null); ar.Execute(); assetUuids = null; } else { m_log.DebugFormat("[ARCHIVER]: Not saving assets since --noassets was specified"); // CloseArchive(string.Empty); } CloseArchive(string.Empty); } catch (Exception e) { CloseArchive(e.Message); throw; } GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce; GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.Default; }
/// <summary> /// Save a backup of the sim /// </summary> /// <param name = "appendedFilePath">The file path where the backup will be saved</param> protected virtual void SaveBackup(string appendedFilePath, bool saveAssets) { if (appendedFilePath == "/") { appendedFilePath = ""; } if (m_scene.RegionInfo.HasBeenDeleted) { return; } IBackupModule backupModule = m_scene.RequestModuleInterface <IBackupModule>(); if (backupModule != null && backupModule.LoadingPrims) //Something is changing lots of prims { MainConsole.Instance.Info("[Backup]: Not saving backup because the backup module is loading prims"); return; } //Save any script state saves that might be around IScriptModule[] engines = m_scene.RequestModuleInterfaces <IScriptModule>(); try { if (engines != null) { #if (!ISWIN) foreach (IScriptModule engine in engines) { if (engine != null) { engine.SaveStateSaves(); } } #else foreach (IScriptModule engine in engines.Where(engine => engine != null)) { engine.SaveStateSaves(); } #endif } } catch (Exception ex) { MainConsole.Instance.WarnFormat("[Backup]: Exception caught: {0}", ex); } MainConsole.Instance.Info("[FileBasedSimulationData]: Saving backup for region " + m_scene.RegionInfo.RegionName); string fileName = appendedFilePath + m_scene.RegionInfo.RegionName + m_saveAppendedFileName + ".abackup"; if (File.Exists(fileName)) { //Do new style saving here! GZipStream m_saveStream = new GZipStream(new FileStream(fileName + ".tmp", FileMode.Create), CompressionMode.Compress); TarArchiveWriter writer = new TarArchiveWriter(m_saveStream); GZipStream m_loadStream = new GZipStream(new FileStream(fileName, FileMode.Open), CompressionMode.Decompress); TarArchiveReader reader = new TarArchiveReader(m_loadStream); writer.WriteDir("parcels"); IParcelManagementModule module = m_scene.RequestModuleInterface <IParcelManagementModule>(); if (module != null) { List <ILandObject> landObject = module.AllParcels(); foreach (ILandObject parcel in landObject) { OSDMap parcelMap = parcel.LandData.ToOSD(); var binary = OSDParser.SerializeLLSDBinary(parcelMap); writer.WriteFile("parcels/" + parcel.LandData.GlobalID.ToString(), binary); binary = null; parcelMap = null; } } writer.WriteDir("newstyleterrain"); writer.WriteDir("newstylerevertterrain"); writer.WriteDir("newstylewater"); writer.WriteDir("newstylerevertwater"); ITerrainModule tModule = m_scene.RequestModuleInterface <ITerrainModule>(); if (tModule != null) { try { byte[] sdata = WriteTerrainToStream(tModule.TerrainMap); writer.WriteFile("newstyleterrain/" + m_scene.RegionInfo.RegionID.ToString() + ".terrain", sdata); sdata = null; sdata = WriteTerrainToStream(tModule.TerrainRevertMap); writer.WriteFile( "newstylerevertterrain/" + m_scene.RegionInfo.RegionID.ToString() + ".terrain", sdata); sdata = null; if (tModule.TerrainWaterMap != null) { sdata = WriteTerrainToStream(tModule.TerrainWaterMap); writer.WriteFile("newstylewater/" + m_scene.RegionInfo.RegionID.ToString() + ".terrain", sdata); sdata = null; sdata = WriteTerrainToStream(tModule.TerrainWaterRevertMap); writer.WriteFile( "newstylerevertwater/" + m_scene.RegionInfo.RegionID.ToString() + ".terrain", sdata); sdata = null; } } catch (Exception ex) { MainConsole.Instance.WarnFormat("[Backup]: Exception caught: {0}", ex); } } IDictionary <UUID, AssetType> assets = new Dictionary <UUID, AssetType>(); UuidGatherer assetGatherer = new UuidGatherer(m_scene.AssetService); ISceneEntity[] saveentities = m_scene.Entities.GetEntities(); List <UUID> entitiesToSave = new List <UUID>(); foreach (ISceneEntity entity in saveentities) { try { if (entity.IsAttachment || ((entity.RootChild.Flags & PrimFlags.Temporary) == PrimFlags.Temporary) || ((entity.RootChild.Flags & PrimFlags.TemporaryOnRez) == PrimFlags.TemporaryOnRez)) { continue; } if (entity.HasGroupChanged) { entity.HasGroupChanged = false; //Write all entities byte[] xml = ((ISceneObject)entity).ToBinaryXml2(); writer.WriteFile("entities/" + entity.UUID.ToString(), xml); xml = null; } else { entitiesToSave.Add(entity.UUID); } if (saveAssets) { assetGatherer.GatherAssetUuids(entity, assets, m_scene); } } catch (Exception ex) { MainConsole.Instance.WarnFormat("[Backup]: Exception caught: {0}", ex); entitiesToSave.Add(entity.UUID); } } byte[] data; string filePath; TarArchiveReader.TarEntryType entryType; //Load the archive data that we need try { while ((data = reader.ReadEntry(out filePath, out entryType)) != null) { if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType) { continue; } if (filePath.StartsWith("entities/")) { UUID entityID = UUID.Parse(filePath.Remove(0, 9)); if (entitiesToSave.Contains(entityID)) { writer.WriteFile(filePath, data); entitiesToSave.Remove(entityID); } } data = null; } } catch (Exception ex) { MainConsole.Instance.WarnFormat("[Backup]: Exception caught: {0}", ex); } if (entitiesToSave.Count > 0) { MainConsole.Instance.Fatal(entitiesToSave.Count + " PRIMS WERE NOT GOING TO BE SAVED! FORCE SAVING NOW! "); foreach (ISceneEntity entity in saveentities) { if (entitiesToSave.Contains(entity.UUID)) { if (entity.IsAttachment || ((entity.RootChild.Flags & PrimFlags.Temporary) == PrimFlags.Temporary) || ((entity.RootChild.Flags & PrimFlags.TemporaryOnRez) == PrimFlags.TemporaryOnRez)) { continue; } //Write all entities byte[] xml = ((ISceneObject)entity).ToBinaryXml2(); writer.WriteFile("entities/" + entity.UUID.ToString(), xml); xml = null; } } } if (saveAssets) { foreach (UUID assetID in new List <UUID>(assets.Keys)) { try { WriteAsset(assetID.ToString(), m_scene.AssetService.Get(assetID.ToString()), writer); } catch (Exception ex) { MainConsole.Instance.WarnFormat("[Backup]: Exception caught: {0}", ex); } } } reader.Close(); writer.Close(); m_loadStream.Close(); m_saveStream.Close(); GC.Collect(); if (m_keepOldSave && !m_oldSaveHasBeenSaved) { //Havn't moved it yet, so make sure the directory exists, then move it m_oldSaveHasBeenSaved = true; if (!Directory.Exists(m_oldSaveDirectory)) { Directory.CreateDirectory(m_oldSaveDirectory); } File.Copy(fileName + ".tmp", Path.Combine(m_oldSaveDirectory, m_scene.RegionInfo.RegionName + SerializeDateTime() + m_saveAppendedFileName + ".abackup")); } //Just remove the file File.Delete(fileName); } else { //Add the .temp since we might need to make a backup and so that if something goes wrong, we don't corrupt the main backup GZipStream m_saveStream = new GZipStream(new FileStream(fileName + ".tmp", FileMode.Create), CompressionMode.Compress); TarArchiveWriter writer = new TarArchiveWriter(m_saveStream); IAuroraBackupArchiver archiver = m_scene.RequestModuleInterface <IAuroraBackupArchiver>(); //Turn off prompting so that we don't ask the user questions every time we need to save the backup archiver.AllowPrompting = false; archiver.SaveRegionBackup(writer, m_scene); archiver.AllowPrompting = true; m_saveStream.Close(); writer.Close(); GC.Collect(); } File.Move(fileName + ".tmp", fileName); ISceneEntity[] entities = m_scene.Entities.GetEntities(); try { #if (!ISWIN) foreach (ISceneEntity entity in entities) { if (entity.HasGroupChanged) { entity.HasGroupChanged = false; } } #else foreach (ISceneEntity entity in entities.Where(entity => entity.HasGroupChanged)) { entity.HasGroupChanged = false; } #endif } catch (Exception ex) { MainConsole.Instance.WarnFormat("[Backup]: Exception caught: {0}", ex); } //Now make it the full file again MapTileNeedsGenerated = true; MainConsole.Instance.Info("[FileBasedSimulationData]: Saved Backup for region " + m_scene.RegionInfo.RegionName); }