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 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); }
protected internal void Save(ICollection <UUID> assetsFoundUuids, ICollection <UUID> assetsNotFoundUuids) { foreach (UUID uuid in assetsNotFoundUuids) { MainConsole.Instance.DebugFormat("[Archiver]: Could not find asset {0}", uuid); } //MainConsole.Instance.InfoFormat( // "[Archiver]: Received {0} of {1} assets requested", assetsFoundUuids.Count, assetsFoundUuids.Count + assetsNotFoundUuids.Count); MainConsole.Instance.InfoFormat("[Archiver]: Creating archive file. This may take some time."); // Write out control file m_archiveWriter.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, Create0p2ControlFile()); MainConsole.Instance.InfoFormat("[Archiver]: Added control file to archive."); // Write out region settings string settingsPath = string.Format("{0}{1}.xml", ArchiveConstants.SETTINGS_PATH, m_scene.RegionInfo.RegionName); m_archiveWriter.WriteFile(settingsPath, RegionSettingsSerializer.Serialize(m_scene.RegionInfo.RegionSettings)); MainConsole.Instance.InfoFormat("[Archiver]: Added region settings to archive."); // Write out land data (aka parcel) settings IParcelManagementModule parcelManagement = m_scene.RequestModuleInterface <IParcelManagementModule>(); if (parcelManagement != null) { List <ILandObject> landObjects = parcelManagement.AllParcels(); foreach (ILandObject lo in landObjects) { LandData landData = lo.LandData; string landDataPath = string.Format("{0}{1}.xml", ArchiveConstants.LANDDATA_PATH, landData.GlobalID); m_archiveWriter.WriteFile(landDataPath, LandDataSerializer.Serialize(landData)); } } MainConsole.Instance.InfoFormat("[Archiver]: Added parcel settings to archive."); // Write out terrain string terrainPath = string.Format("{0}{1}.r32", ArchiveConstants.TERRAINS_PATH, m_scene.RegionInfo.RegionName); MemoryStream ms = new MemoryStream(); m_terrainModule.SaveToStream(m_terrainModule.TerrainMap, terrainPath, ms); m_archiveWriter.WriteFile(terrainPath, ms.ToArray()); ms.Close(); MainConsole.Instance.InfoFormat("[Archiver]: Added terrain information to archive."); // Write out scene object metadata foreach (ISceneEntity sceneObject in m_sceneObjects) { //MainConsole.Instance.DebugFormat("[Archiver]: Saving {0} {1}, {2}", entity.Name, entity.UUID, entity.GetType()); string serializedObject = m_serializer.SerializeGroupToXml2(sceneObject); if (serializedObject != null) { m_archiveWriter.WriteFile(ArchiveHelpers.CreateObjectPath(sceneObject), serializedObject); } } MainConsole.Instance.InfoFormat("[Archiver]: Added scene objects to archive."); }
protected internal void ReceivedAllAssets( ICollection <UUID> assetsFoundUuids, ICollection <UUID> assetsNotFoundUuids) { foreach (UUID uuid in assetsNotFoundUuids) { m_log.DebugFormat("[ARCHIVER]: Could not find asset {0}", uuid); } // m_log.InfoFormat( // "[ARCHIVER]: Received {0} of {1} assets requested", // assetsFoundUuids.Count, assetsFoundUuids.Count + assetsNotFoundUuids.Count); m_log.InfoFormat("[ARCHIVER]: Creating archive file. This may take some time."); // Write out control file m_archiveWriter.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, Create0p2ControlFile()); m_log.InfoFormat("[ARCHIVER]: Added control file to archive."); // Write out region settings string settingsPath = String.Format("{0}{1}.xml", ArchiveConstants.SETTINGS_PATH, m_scene.RegionInfo.RegionName); m_archiveWriter.WriteFile(settingsPath, RegionSettingsSerializer.Serialize(m_scene.RegionInfo.RegionSettings)); m_log.InfoFormat("[ARCHIVER]: Added region settings to archive."); // Write out terrain string terrainPath = String.Format("{0}{1}.r32", ArchiveConstants.TERRAINS_PATH, m_scene.RegionInfo.RegionName); MemoryStream ms = new MemoryStream(); m_terrainModule.SaveToStream(terrainPath, ms); m_archiveWriter.WriteFile(terrainPath, ms.ToArray()); ms.Close(); m_log.InfoFormat("[ARCHIVER]: Added terrain information to archive."); // Write out scene object metadata foreach (SceneObjectGroup sceneObject in m_sceneObjects) { //m_log.DebugFormat("[ARCHIVER]: Saving {0} {1}, {2}", entity.Name, entity.UUID, entity.GetType()); Vector3 position = sceneObject.AbsolutePosition; string serializedObject = m_serialiser.SerializeGroupToXml2(sceneObject); string filename = string.Format( "{0}{1}_{2:000}-{3:000}-{4:000}__{5}.xml", ArchiveConstants.OBJECTS_PATH, sceneObject.Name, Math.Round(position.X), Math.Round(position.Y), Math.Round(position.Z), sceneObject.UUID); m_archiveWriter.WriteFile(filename, serializedObject); } m_log.InfoFormat("[ARCHIVER]: Added scene objects to archive."); m_archiveWriter.Close(); m_log.InfoFormat("[ARCHIVER]: Finished writing out OAR for {0}", m_scene.RegionInfo.RegionName); m_scene.EventManager.TriggerOarFileSaved(m_requestId, String.Empty); }
/// <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 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, OSDParser.SerializeLLSDBinary(parcelMap)); } } 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 = 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"); }
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); } } } } }
/// <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; } }
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()); }
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"); }
/// <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(); }
/// <summary> /// Write an assets metadata file to the given archive /// </summary> /// <param name="archive"></param> // protected void WriteMetadata(TarArchiveWriter archive) // { // StringWriter sw = new StringWriter(); // XmlTextWriter xtw = new XmlTextWriter(sw); // // xtw.Formatting = Formatting.Indented; // xtw.WriteStartDocument(); // // xtw.WriteStartElement("assets"); // // foreach (UUID uuid in m_assets.Keys) // { // AssetBase asset = m_assets[uuid]; // // if (asset != null) // { // xtw.WriteStartElement("asset"); // // string extension = String.Empty; // // if (ArchiveConstants.ASSET_TYPE_TO_EXTENSION.ContainsKey(asset.Type)) // { // extension = ArchiveConstants.ASSET_TYPE_TO_EXTENSION[asset.Type]; // } // // xtw.WriteElementString("filename", uuid.ToString() + extension); // // xtw.WriteElementString("name", asset.Name); // xtw.WriteElementString("description", asset.Description); // xtw.WriteElementString("asset-type", asset.Type.ToString()); // // xtw.WriteEndElement(); // } // } // // xtw.WriteEndElement(); // // xtw.WriteEndDocument(); // // archive.WriteFile("assets.xml", sw.ToString()); // } /// <summary> /// Write asset data files to the given archive /// </summary> /// <param name="asset"></param> protected void WriteData(AssetBase asset) { // It appears that gtar, at least, doesn't need the intermediate directory entries in the tar //archive.AddDir("assets"); string extension = String.Empty; if (ArchiveConstants.ASSET_TYPE_TO_EXTENSION.ContainsKey(asset.Type)) { extension = ArchiveConstants.ASSET_TYPE_TO_EXTENSION[asset.Type]; } else { m_log.ErrorFormat( "[ARCHIVER]: Unrecognized asset type {0} with uuid {1}. This asset will be saved but not reloaded", asset.Type, asset.ID); } // Check for Thoosa Inventory object and decode to XML if necessary for Archive. string xmlData; if ((asset.Type == (sbyte)AssetType.Object) && (m_inventorySerializer != null) && (m_inventorySerializer.CanDeserialize(asset.Data))) { if (m_inventorySerializer.IsValidCoalesced(asset.Data)) { CoalescedObject obj = m_inventorySerializer.DeserializeCoalescedObjFromInventoryBytes(asset.Data); List <ItemPermissionBlock> perms = new List <ItemPermissionBlock>(); foreach (var grp in obj.Groups) { perms.Add(obj.FindPermissions(grp.UUID)); } xmlData = CoalescedSceneObjectSerializer.ToXmlFormat(obj.Groups, perms, StopScriptReason.None); } else if (m_inventorySerializer.IsValidGroup(asset.Data)) { SceneObjectGroup grp = m_inventorySerializer.DeserializeGroupFromInventoryBytes(asset.Data); xmlData = m_serializer.SaveGroupToOriginalXml(grp); } else { return; // can't pass the CanDeserialize test above, but makes the compiler happy } // Now write out the XML format asset m_archiveWriter.WriteFile( ArchiveConstants.ASSETS_PATH + asset.FullID.ToString() + extension, xmlData); } else { // Now write out the same (raw) asset unchanged. m_archiveWriter.WriteFile( ArchiveConstants.ASSETS_PATH + asset.FullID.ToString() + extension, asset.Data); } m_assetsWritten++; if (m_assetsWritten % LOG_ASSET_LOAD_NOTIFICATION_INTERVAL == 0) { m_log.InfoFormat("[ARCHIVER]: Added {0} assets to archive", m_assetsWritten); } }
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(); }
private void WriteAsset(AssetBase asset, TarArchiveWriter writer) { writer.WriteFile("assets", asset.Data); }
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()); }
/// <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; }
protected void SaveInvItem(InventoryItemBase inventoryItem, string path, Dictionary <string, object> options, IUserAccountService userAccountService) { if (options.ContainsKey("exclude")) { if (((List <String>)options["exclude"]).Contains(inventoryItem.Name) || ((List <String>)options["exclude"]).Contains(inventoryItem.ID.ToString())) { if (options.ContainsKey("verbose")) { m_log.InfoFormat( "[INVENTORY ARCHIVER]: Skipping inventory item {0} {1} at {2}", inventoryItem.Name, inventoryItem.ID, path); } return; } } if (options.ContainsKey("verbose")) { m_log.InfoFormat( "[INVENTORY ARCHIVER]: Saving item {0} {1} (asset UUID {2})", inventoryItem.ID, inventoryItem.Name, inventoryItem.AssetID); } string filename = path + CreateArchiveItemName(inventoryItem); // Record the creator of this item for user record purposes (which might go away soon) m_userUuids[inventoryItem.CreatorIdAsUuid] = 1; string serialization = UserInventoryItemSerializer.Serialize(inventoryItem, options, userAccountService); m_archiveWriter.WriteFile(filename, serialization); AssetType itemAssetType = (AssetType)inventoryItem.AssetType; // Don't chase down link asset items as they actually point to their target item IDs rather than an asset if (SaveAssets && itemAssetType != AssetType.Link && itemAssetType != AssetType.LinkFolder) { int curErrorCntr = m_assetGatherer.ErrorCount; int possible = m_assetGatherer.possibleNotAssetCount; m_assetGatherer.AddForInspection(inventoryItem.AssetID); m_assetGatherer.GatherAll(); curErrorCntr = m_assetGatherer.ErrorCount - curErrorCntr; possible = m_assetGatherer.possibleNotAssetCount - possible; if (curErrorCntr > 0 || possible > 0) { string spath; int indx = path.IndexOf("__"); if (indx > 0) { spath = path.Substring(0, indx); } else { spath = path; } if (curErrorCntr > 0) { m_log.ErrorFormat("[INVENTORY ARCHIVER Warning]: item {0} '{1}', type {2}, in '{3}', contains {4} references to missing or damaged assets", inventoryItem.ID, inventoryItem.Name, itemAssetType.ToString(), spath, curErrorCntr); if (possible > 0) { m_log.WarnFormat("[INVENTORY ARCHIVER Warning]: item also contains {0} references that may be to missing or damaged assets or not a problem", possible); } } else if (possible > 0) { m_log.WarnFormat("[INVENTORY ARCHIVER Warning]: item {0} '{1}', type {2}, in '{3}', contains {4} references that may be to missing or damaged assets or not a problem", inventoryItem.ID, inventoryItem.Name, itemAssetType.ToString(), spath, possible); } } } }
/// <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; } }
/// <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); }