From ce468215d576cc301a261d85bee9baa68a246ce6 Mon Sep 17 00:00:00 2001 From: Oren Hurvitz Date: Tue, 24 Jul 2012 19:48:08 +0300 Subject: Support multi-region OAR files Merged ArchiveWriteRequestPreparation.cs and ArchiveWriteRequestExecution.cs. This simplifies the code, and it's faster to write each scene to the archive as it's found rather than all at once at the end. --- .../World/Archiver/ArchiveReadRequest.cs | 365 ++++++++++++++++----- 1 file changed, 282 insertions(+), 83 deletions(-) (limited to 'OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs') diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs index 433166d..a6923ef 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs @@ -43,6 +43,7 @@ using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes.Serialization; using OpenSim.Services.Interfaces; +using System.Threading; namespace OpenSim.Region.CoreModules.World.Archiver { @@ -52,7 +53,30 @@ namespace OpenSim.Region.CoreModules.World.Archiver public class ArchiveReadRequest { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// Contains data used while dearchiving a single scene. + /// + private class DearchiveContext + { + public Scene Scene { get; set; } + + public List SerialisedSceneObjects { get; set; } + + public List SerialisedParcels { get; set; } + + public List SceneObjects { get; set; } + + public DearchiveContext(Scene scene) + { + Scene = scene; + SerialisedSceneObjects = new List(); + SerialisedParcels = new List(); + SceneObjects = new List(); + } + } + /// /// The maximum major version of OAR that we can read. Minor versions shouldn't need a max number since version /// bumps here should be compatible. @@ -62,9 +86,10 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// /// Has the control file been loaded for this archive? /// - public bool ControlFileLoaded { get; private set; } + public bool ControlFileLoaded { get; private set; } - protected Scene m_scene; + protected string m_loadPath; + protected Scene m_rootScene; protected Stream m_loadStream; protected Guid m_requestId; protected string m_errorMessage; @@ -91,7 +116,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver { if (m_UserMan == null) { - m_UserMan = m_scene.RequestModuleInterface(); + m_UserMan = m_rootScene.RequestModuleInterface(); } return m_UserMan; } @@ -104,10 +129,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver private IGroupsModule m_groupsModule; + private IAssetService m_assetService = null; + + public ArchiveReadRequest(Scene scene, string loadPath, bool merge, bool skipAssets, Guid requestId) { - m_scene = scene; + m_rootScene = scene; + m_loadPath = loadPath; try { m_loadStream = new GZipStream(ArchiveHelpers.GetStream(loadPath), CompressionMode.Decompress); @@ -128,12 +157,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver // Zero can never be a valid user id m_validUserUuids[UUID.Zero] = false; - m_groupsModule = m_scene.RequestModuleInterface(); + m_groupsModule = m_rootScene.RequestModuleInterface(); + m_assetService = m_rootScene.AssetService; } public ArchiveReadRequest(Scene scene, Stream loadStream, bool merge, bool skipAssets, Guid requestId) { - m_scene = scene; + m_rootScene = scene; + m_loadPath = null; m_loadStream = loadStream; m_merge = merge; m_skipAssets = skipAssets; @@ -142,7 +173,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver // Zero can never be a valid user id m_validUserUuids[UUID.Zero] = false; - m_groupsModule = m_scene.RequestModuleInterface(); + m_groupsModule = m_rootScene.RequestModuleInterface(); + m_assetService = m_rootScene.AssetService; } /// @@ -150,25 +182,25 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// public void DearchiveRegion() { - // The same code can handle dearchiving 0.1 and 0.2 OpenSim Archive versions - DearchiveRegion0DotStar(); - } - - private void DearchiveRegion0DotStar() - { int successfulAssetRestores = 0; int failedAssetRestores = 0; - List serialisedSceneObjects = new List(); - List serialisedParcels = new List(); - string filePath = "NONE"; - TarArchiveReader archive = new TarArchiveReader(m_loadStream); + DearchiveScenesInfo dearchivedScenes; + + // We dearchive all the scenes at once, because the files in the TAR archive might be mixed. + // Therefore, we have to keep track of the dearchive context of all the scenes. + Dictionary sceneContexts = new Dictionary(); + + string fullPath = "NONE"; + TarArchiveReader archive = null; byte[] data; TarArchiveReader.TarEntryType entryType; - + try { - while ((data = archive.ReadEntry(out filePath, out entryType)) != null) + FindAndLoadControlFile(out archive, out dearchivedScenes); + + while ((data = archive.ReadEntry(out fullPath, out entryType)) != null) { //m_log.DebugFormat( // "[ARCHIVER]: Successfully read {0} ({1} bytes)", filePath, data.Length); @@ -176,9 +208,30 @@ namespace OpenSim.Region.CoreModules.World.Archiver if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType) continue; + + // Find the scene that this file belongs to + + Scene scene; + string filePath; + if (!dearchivedScenes.GetRegionFromPath(fullPath, out scene, out filePath)) + continue; // this file belongs to a region that we're not loading + + DearchiveContext sceneContext = null; + if (scene != null) + { + if (!sceneContexts.TryGetValue(scene.RegionInfo.RegionID, out sceneContext)) + { + sceneContext = new DearchiveContext(scene); + sceneContexts.Add(scene.RegionInfo.RegionID, sceneContext); + } + } + + + // Process the file + if (filePath.StartsWith(ArchiveConstants.OBJECTS_PATH)) { - serialisedSceneObjects.Add(Encoding.UTF8.GetString(data)); + sceneContext.SerialisedSceneObjects.Add(Encoding.UTF8.GetString(data)); } else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH) && !m_skipAssets) { @@ -192,19 +245,19 @@ namespace OpenSim.Region.CoreModules.World.Archiver } else if (!m_merge && filePath.StartsWith(ArchiveConstants.TERRAINS_PATH)) { - LoadTerrain(filePath, data); + LoadTerrain(scene, filePath, data); } else if (!m_merge && filePath.StartsWith(ArchiveConstants.SETTINGS_PATH)) { - LoadRegionSettings(filePath, data); + LoadRegionSettings(scene, filePath, data, dearchivedScenes); } else if (!m_merge && filePath.StartsWith(ArchiveConstants.LANDDATA_PATH)) { - serialisedParcels.Add(Encoding.UTF8.GetString(data)); + sceneContext.SerialisedParcels.Add(Encoding.UTF8.GetString(data)); } else if (filePath == ArchiveConstants.CONTROL_FILE_PATH) { - LoadControlFile(filePath, data); + // Ignore, because we already read the control file } } @@ -212,15 +265,16 @@ namespace OpenSim.Region.CoreModules.World.Archiver } catch (Exception e) { - m_log.ErrorFormat( - "[ARCHIVER]: Aborting load with error in archive file {0}. {1}", filePath, e); + m_log.Error( + String.Format("[ARCHIVER]: Aborting load with error in archive file {0} ", fullPath), e); m_errorMessage += e.ToString(); - m_scene.EventManager.TriggerOarFileLoaded(m_requestId, m_errorMessage); + m_rootScene.EventManager.TriggerOarFileLoaded(m_requestId, new List(), m_errorMessage); return; } finally { - archive.Close(); + if (archive != null) + archive.Close(); } if (!m_skipAssets) @@ -234,32 +288,143 @@ namespace OpenSim.Region.CoreModules.World.Archiver } } - if (!m_merge) + foreach (DearchiveContext sceneContext in sceneContexts.Values) { - m_log.Info("[ARCHIVER]: Clearing all existing scene objects"); - m_scene.DeleteAllSceneObjects(); + m_log.InfoFormat("[ARCHIVER:] Loading region {0}", sceneContext.Scene.RegionInfo.RegionName); + + if (!m_merge) + { + m_log.Info("[ARCHIVER]: Clearing all existing scene objects"); + sceneContext.Scene.DeleteAllSceneObjects(); + } + + try + { + LoadParcels(sceneContext.Scene, sceneContext.SerialisedParcels); + LoadObjects(sceneContext.Scene, sceneContext.SerialisedSceneObjects, sceneContext.SceneObjects); + + // Inform any interested parties that the region has changed. We waited until now so that all + // of the region's objects will be loaded when we send this notification. + IEstateModule estateModule = sceneContext.Scene.RequestModuleInterface(); + if (estateModule != null) + estateModule.TriggerRegionInfoChange(); + } + catch (Exception e) + { + m_log.Error("[ARCHIVER]: Error loading parcels or objects ", e); + m_errorMessage += e.ToString(); + m_rootScene.EventManager.TriggerOarFileLoaded(m_requestId, new List(), m_errorMessage); + return; + } } - LoadParcels(serialisedParcels); - LoadObjects(serialisedSceneObjects); + // Start the scripts. We delayed this because we want the OAR to finish loading ASAP, so + // that users can enter the scene. If we allow the scripts to start in the loop above + // then they significantly increase the time until the OAR finishes loading. + Util.FireAndForget(delegate(object o) + { + Thread.Sleep(15000); + m_log.Info("Starting scripts in scene objects"); + + foreach (DearchiveContext sceneContext in sceneContexts.Values) + { + foreach (SceneObjectGroup sceneObject in sceneContext.SceneObjects) + { + sceneObject.CreateScriptInstances(0, false, sceneContext.Scene.DefaultScriptEngine, 0); // StateSource.RegionStart + sceneObject.ResumeScripts(); + } + + sceneContext.SceneObjects.Clear(); + } + }); m_log.InfoFormat("[ARCHIVER]: Successfully loaded archive"); - m_scene.EventManager.TriggerOarFileLoaded(m_requestId, m_errorMessage); + m_rootScene.EventManager.TriggerOarFileLoaded(m_requestId, dearchivedScenes.GetLoadedScenes(), m_errorMessage); + } + + /// + /// Searches through the files in the archive for the control file, and reads it. + /// We must read the control file first, in order to know which regions are available. + /// + /// + /// In most cases the control file *is* first, since that's how we create archives. However, + /// it's possible that someone rewrote the archive externally so we can't rely on this fact. + /// + /// + /// + private void FindAndLoadControlFile(out TarArchiveReader archive, out DearchiveScenesInfo dearchivedScenes) + { + archive = new TarArchiveReader(m_loadStream); + dearchivedScenes = new DearchiveScenesInfo(); + + string filePath; + byte[] data; + TarArchiveReader.TarEntryType entryType; + bool firstFile = true; + + while ((data = archive.ReadEntry(out filePath, out entryType)) != null) + { + if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType) + continue; + + if (filePath == ArchiveConstants.CONTROL_FILE_PATH) + { + LoadControlFile(filePath, data, dearchivedScenes); + + // Find which scenes are available in the simulator + ArchiveScenesGroup simulatorScenes = new ArchiveScenesGroup(); + SceneManager.Instance.ForEachScene(delegate(Scene scene2) + { + simulatorScenes.AddScene(scene2); + }); + simulatorScenes.CalcSceneLocations(); + dearchivedScenes.SetSimulatorScenes(m_rootScene, simulatorScenes); + + // If the control file wasn't the first file then reset the read pointer + if (!firstFile) + { + m_log.Warn("Control file wasn't the first file in the archive"); + if (m_loadStream.CanSeek) + { + m_loadStream.Seek(0, SeekOrigin.Begin); + } + else if (m_loadPath != null) + { + archive.Close(); + archive = null; + m_loadStream.Close(); + m_loadStream = null; + m_loadStream = new GZipStream(ArchiveHelpers.GetStream(m_loadPath), CompressionMode.Decompress); + archive = new TarArchiveReader(m_loadStream); + } + else + { + // There isn't currently a scenario where this happens, but it's best to add a check just in case + throw new Exception("Error reading archive: control file wasn't the first file, and the input stream doesn't allow seeking"); + } + } + + return; + } + + firstFile = false; + } + + throw new Exception("Control file not found"); } /// /// Load serialized scene objects. /// - /// - protected void LoadObjects(List serialisedSceneObjects) + protected void LoadObjects(Scene scene, List serialisedSceneObjects, List sceneObjects) { // Reload serialized prims m_log.InfoFormat("[ARCHIVER]: Loading {0} scene objects. Please wait.", serialisedSceneObjects.Count); - UUID oldTelehubUUID = m_scene.RegionInfo.RegionSettings.TelehubObject; + UUID oldTelehubUUID = scene.RegionInfo.RegionSettings.TelehubObject; - IRegionSerialiserModule serialiser = m_scene.RequestModuleInterface(); + IRegionSerialiserModule serialiser = scene.RequestModuleInterface(); int sceneObjectsLoadedCount = 0; foreach (string serialisedSceneObject in serialisedSceneObjects) @@ -280,7 +445,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver SceneObjectGroup sceneObject = serialiser.DeserializeGroupFromXml2(serialisedSceneObject); - bool isTelehub = (sceneObject.UUID == oldTelehubUUID); + bool isTelehub = (sceneObject.UUID == oldTelehubUUID) && (oldTelehubUUID != UUID.Zero); // For now, give all incoming scene objects new uuids. This will allow scenes to be cloned // on the same region server and multiple examples a single object archive to be imported @@ -290,8 +455,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver if (isTelehub) { // Change the Telehub Object to the new UUID - m_scene.RegionInfo.RegionSettings.TelehubObject = sceneObject.UUID; - m_scene.RegionInfo.RegionSettings.Save(); + scene.RegionInfo.RegionSettings.TelehubObject = sceneObject.UUID; + scene.RegionInfo.RegionSettings.Save(); oldTelehubUUID = UUID.Zero; } @@ -301,17 +466,17 @@ namespace OpenSim.Region.CoreModules.World.Archiver { if (part.CreatorData == null || part.CreatorData == string.Empty) { - if (!ResolveUserUuid(part.CreatorID)) - part.CreatorID = m_scene.RegionInfo.EstateSettings.EstateOwner; + if (!ResolveUserUuid(scene, part.CreatorID)) + part.CreatorID = scene.RegionInfo.EstateSettings.EstateOwner; } if (UserManager != null) UserManager.AddUser(part.CreatorID, part.CreatorData); - if (!ResolveUserUuid(part.OwnerID)) - part.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; + if (!ResolveUserUuid(scene, part.OwnerID)) + part.OwnerID = scene.RegionInfo.EstateSettings.EstateOwner; - if (!ResolveUserUuid(part.LastOwnerID)) - part.LastOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; + if (!ResolveUserUuid(scene, part.LastOwnerID)) + part.LastOwnerID = scene.RegionInfo.EstateSettings.EstateOwner; if (!ResolveGroupUuid(part.GroupID)) part.GroupID = UUID.Zero; @@ -328,15 +493,15 @@ namespace OpenSim.Region.CoreModules.World.Archiver TaskInventoryDictionary inv = part.TaskInventory; foreach (KeyValuePair kvp in inv) { - if (!ResolveUserUuid(kvp.Value.OwnerID)) + if (!ResolveUserUuid(scene, kvp.Value.OwnerID)) { - kvp.Value.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; + kvp.Value.OwnerID = scene.RegionInfo.EstateSettings.EstateOwner; } if (kvp.Value.CreatorData == null || kvp.Value.CreatorData == string.Empty) { - if (!ResolveUserUuid(kvp.Value.CreatorID)) - kvp.Value.CreatorID = m_scene.RegionInfo.EstateSettings.EstateOwner; + if (!ResolveUserUuid(scene, kvp.Value.CreatorID)) + kvp.Value.CreatorID = scene.RegionInfo.EstateSettings.EstateOwner; } if (UserManager != null) @@ -348,10 +513,10 @@ namespace OpenSim.Region.CoreModules.World.Archiver } } - if (m_scene.AddRestoredSceneObject(sceneObject, true, false)) + if (scene.AddRestoredSceneObject(sceneObject, true, false)) { sceneObjectsLoadedCount++; - sceneObject.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, 0); + sceneObject.CreateScriptInstances(0, false, scene.DefaultScriptEngine, 0); sceneObject.ResumeScripts(); } } @@ -366,16 +531,17 @@ namespace OpenSim.Region.CoreModules.World.Archiver if (oldTelehubUUID != UUID.Zero) { m_log.WarnFormat("Telehub object not found: {0}", oldTelehubUUID); - m_scene.RegionInfo.RegionSettings.TelehubObject = UUID.Zero; - m_scene.RegionInfo.RegionSettings.ClearSpawnPoints(); + scene.RegionInfo.RegionSettings.TelehubObject = UUID.Zero; + scene.RegionInfo.RegionSettings.ClearSpawnPoints(); } } /// /// Load serialized parcels. /// + /// /// - protected void LoadParcels(List serialisedParcels) + protected void LoadParcels(Scene scene, List serialisedParcels) { // Reload serialized parcels m_log.InfoFormat("[ARCHIVER]: Loading {0} parcels. Please wait.", serialisedParcels.Count); @@ -386,8 +552,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver // Validate User and Group UUID's - if (!ResolveUserUuid(parcel.OwnerID)) - parcel.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; + if (!ResolveUserUuid(scene, parcel.OwnerID)) + parcel.OwnerID = m_rootScene.RegionInfo.EstateSettings.EstateOwner; if (!ResolveGroupUuid(parcel.GroupID)) { @@ -398,7 +564,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver List accessList = new List(); foreach (LandAccessEntry entry in parcel.ParcelAccessList) { - if (ResolveUserUuid(entry.AgentID)) + if (ResolveUserUuid(scene, entry.AgentID)) accessList.Add(entry); // else, drop this access rule } @@ -414,23 +580,24 @@ namespace OpenSim.Region.CoreModules.World.Archiver if (!m_merge) { bool setupDefaultParcel = (landData.Count == 0); - m_scene.LandChannel.Clear(setupDefaultParcel); + scene.LandChannel.Clear(setupDefaultParcel); } - m_scene.EventManager.TriggerIncomingLandDataFromStorage(landData); + scene.EventManager.TriggerIncomingLandDataFromStorage(landData); m_log.InfoFormat("[ARCHIVER]: Restored {0} parcels.", landData.Count); } /// /// Look up the given user id to check whether it's one that is valid for this grid. /// + /// /// /// - private bool ResolveUserUuid(UUID uuid) + private bool ResolveUserUuid(Scene scene, UUID uuid) { if (!m_validUserUuids.ContainsKey(uuid)) { - UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, uuid); + UserAccount account = scene.UserAccountService.GetUserAccount(scene.RegionInfo.ScopeID, uuid); m_validUserUuids.Add(uuid, account != null); } @@ -485,7 +652,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver string extension = filename.Substring(i); string uuid = filename.Remove(filename.Length - extension.Length); - if (m_scene.AssetService.GetMetadata(uuid) != null) + if (m_assetService.GetMetadata(uuid) != null) { // m_log.DebugFormat("[ARCHIVER]: found existing asset {0}",uuid); return true; @@ -505,7 +672,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver // We're relying on the asset service to do the sensible thing and not store the asset if it already // exists. - m_scene.AssetService.Store(asset); + m_assetService.Store(asset); /** * Create layers on decode for image assets. This is likely to significantly increase the time to load archives so @@ -533,12 +700,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// /// Load region settings data /// + /// /// /// + /// /// /// true if settings were loaded successfully, false otherwise /// - private bool LoadRegionSettings(string settingsPath, byte[] data) + private bool LoadRegionSettings(Scene scene, string settingsPath, byte[] data, DearchiveScenesInfo dearchivedScenes) { RegionSettings loadedRegionSettings; @@ -554,7 +723,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver return false; } - RegionSettings currentRegionSettings = m_scene.RegionInfo.RegionSettings; + RegionSettings currentRegionSettings = scene.RegionInfo.RegionSettings; currentRegionSettings.AgentLimit = loadedRegionSettings.AgentLimit; currentRegionSettings.AllowDamage = loadedRegionSettings.AllowDamage; @@ -591,12 +760,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver foreach (SpawnPoint sp in loadedRegionSettings.SpawnPoints()) currentRegionSettings.AddSpawnPoint(sp); + currentRegionSettings.LoadedCreationDateTime = dearchivedScenes.LoadedCreationDateTime; + currentRegionSettings.LoadedCreationID = dearchivedScenes.GetOriginalRegionID(scene.RegionInfo.RegionID).ToString(); + currentRegionSettings.Save(); - m_scene.TriggerEstateSunUpdate(); + scene.TriggerEstateSunUpdate(); - IEstateModule estateModule = m_scene.RequestModuleInterface(); - + IEstateModule estateModule = scene.RequestModuleInterface(); if (estateModule != null) estateModule.sendRegionHandshakeToAll(); @@ -606,14 +777,15 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// /// Load terrain data /// + /// /// /// /// /// true if terrain was resolved successfully, false otherwise. /// - private bool LoadTerrain(string terrainPath, byte[] data) + private bool LoadTerrain(Scene scene, string terrainPath, byte[] data) { - ITerrainModule terrainModule = m_scene.RequestModuleInterface(); + ITerrainModule terrainModule = scene.RequestModuleInterface(); MemoryStream ms = new MemoryStream(data); terrainModule.LoadFromStream(terrainPath, ms); @@ -629,17 +801,18 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// /// /// - public void LoadControlFile(string path, byte[] data) + /// + public DearchiveScenesInfo LoadControlFile(string path, byte[] data, DearchiveScenesInfo dearchivedScenes) { XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable()); XmlParserContext context = new XmlParserContext(null, nsmgr, null, XmlSpace.None); XmlTextReader xtr = new XmlTextReader(Encoding.ASCII.GetString(data), XmlNodeType.Document, context); - RegionSettings currentRegionSettings = m_scene.RegionInfo.RegionSettings; + // Loaded metadata will be empty if no information exists in the archive + dearchivedScenes.LoadedCreationDateTime = 0; + dearchivedScenes.DefaultOriginalID = ""; - // Loaded metadata will empty if no information exists in the archive - currentRegionSettings.LoadedCreationDateTime = 0; - currentRegionSettings.LoadedCreationID = ""; + bool multiRegion = false; while (xtr.Read()) { @@ -665,18 +838,44 @@ namespace OpenSim.Region.CoreModules.World.Archiver { int value; if (Int32.TryParse(xtr.ReadElementContentAsString(), out value)) - currentRegionSettings.LoadedCreationDateTime = value; + dearchivedScenes.LoadedCreationDateTime = value; } - else if (xtr.Name.ToString() == "id") + else if (xtr.Name.ToString() == "row") + { + multiRegion = true; + dearchivedScenes.StartRow(); + } + else if (xtr.Name.ToString() == "region") { - currentRegionSettings.LoadedCreationID = xtr.ReadElementContentAsString(); + dearchivedScenes.StartRegion(); + } + else if (xtr.Name.ToString() == "id") + { + string id = xtr.ReadElementContentAsString(); + dearchivedScenes.DefaultOriginalID = id; + if (multiRegion) + dearchivedScenes.SetRegionOriginalID(id); + } + else if (xtr.Name.ToString() == "dir") + { + dearchivedScenes.SetRegionDirectory(xtr.ReadElementContentAsString()); } } } - - currentRegionSettings.Save(); - + + dearchivedScenes.MultiRegionFormat = multiRegion; + if (!multiRegion) + { + // Add the single scene + dearchivedScenes.StartRow(); + dearchivedScenes.StartRegion(); + dearchivedScenes.SetRegionOriginalID(dearchivedScenes.DefaultOriginalID); + dearchivedScenes.SetRegionDirectory(""); + } + ControlFileLoaded = true; + + return dearchivedScenes; } } } \ No newline at end of file -- cgit v1.1