/// <summary> /// Dearchive the region embodied in this request. /// </summary> public void DearchiveRegion() { int successfulAssetRestores = 0; int failedAssetRestores = 0; 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 <UUID, DearchiveContext> sceneContexts = new Dictionary <UUID, DearchiveContext>(); string fullPath = "NONE"; TarArchiveReader archive = null; byte[] data; TarArchiveReader.TarEntryType entryType; try { 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); 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)) { sceneContext.SerialisedSceneObjects.Add(Encoding.UTF8.GetString(data)); } else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH) && !m_skipAssets) { if (LoadAsset(filePath, data)) { successfulAssetRestores++; } else { failedAssetRestores++; } if ((successfulAssetRestores + failedAssetRestores) % 250 == 0) { m_log.Debug("[ARCHIVER]: Loaded " + successfulAssetRestores + " assets and failed to load " + failedAssetRestores + " assets..."); } } else if (!m_merge && filePath.StartsWith(ArchiveConstants.TERRAINS_PATH)) { LoadTerrain(scene, filePath, data); } else if (!m_merge && filePath.StartsWith(ArchiveConstants.SETTINGS_PATH)) { LoadRegionSettings(scene, filePath, data, dearchivedScenes); } else if (!m_merge && filePath.StartsWith(ArchiveConstants.LANDDATA_PATH)) { sceneContext.SerialisedParcels.Add(Encoding.UTF8.GetString(data)); } else if (filePath == ArchiveConstants.CONTROL_FILE_PATH) { // Ignore, because we already read the control file } } //m_log.Debug("[ARCHIVER]: Reached end of archive"); } catch (Exception e) { m_log.Error( String.Format("[ARCHIVER]: Aborting load with error in archive file {0} ", fullPath), e); m_errorMessage += e.ToString(); m_rootScene.EventManager.TriggerOarFileLoaded(m_requestId, new List <UUID>(), m_errorMessage); return; } finally { if (archive != null) { archive.Close(); } } if (!m_skipAssets) { m_log.InfoFormat("[ARCHIVER]: Restored {0} assets", successfulAssetRestores); if (failedAssetRestores > 0) { m_log.ErrorFormat("[ARCHIVER]: Failed to load {0} assets", failedAssetRestores); m_errorMessage += String.Format("Failed to load {0} assets", failedAssetRestores); } } foreach (DearchiveContext sceneContext in sceneContexts.Values) { 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 <IEstateModule>(); 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 <UUID>(), m_errorMessage); return; } } // 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("[ARCHIVER]: 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_rootScene.EventManager.TriggerOarFileLoaded(m_requestId, dearchivedScenes.GetLoadedScenes(), m_errorMessage); }
/// <summary> /// Dearchive the region embodied in this request. /// </summary> public void DearchiveRegion() { int successfulAssetRestores = 0; int failedAssetRestores = 0; 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<UUID, DearchiveContext> sceneContexts = new Dictionary<UUID, DearchiveContext>(); string fullPath = "NONE"; TarArchiveReader archive = null; byte[] data; TarArchiveReader.TarEntryType entryType; try { 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); 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)) { sceneContext.SerialisedSceneObjects.Add(Encoding.UTF8.GetString(data)); } else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH) && !m_skipAssets) { if (LoadAsset(filePath, data)) successfulAssetRestores++; else failedAssetRestores++; if ((successfulAssetRestores + failedAssetRestores) % 250 == 0) m_log.Debug("[ARCHIVER]: Loaded " + successfulAssetRestores + " assets and failed to load " + failedAssetRestores + " assets..."); } else if (!m_merge && filePath.StartsWith(ArchiveConstants.TERRAINS_PATH)) { LoadTerrain(scene, filePath, data); } else if (!m_merge && filePath.StartsWith(ArchiveConstants.SETTINGS_PATH)) { LoadRegionSettings(scene, filePath, data, dearchivedScenes); } else if (!m_merge && filePath.StartsWith(ArchiveConstants.LANDDATA_PATH)) { sceneContext.SerialisedParcels.Add(Encoding.UTF8.GetString(data)); } else if (filePath == ArchiveConstants.CONTROL_FILE_PATH) { // Ignore, because we already read the control file } } //m_log.Debug("[ARCHIVER]: Reached end of archive"); } catch (Exception e) { m_log.Error( String.Format("[ARCHIVER]: Aborting load with error in archive file {0} ", fullPath), e); m_errorMessage += e.ToString(); m_rootScene.EventManager.TriggerOarFileLoaded(m_requestId, new List<UUID>(), m_errorMessage); return; } finally { if (archive != null) archive.Close(); } if (!m_skipAssets) { m_log.InfoFormat("[ARCHIVER]: Restored {0} assets", successfulAssetRestores); if (failedAssetRestores > 0) { m_log.ErrorFormat("[ARCHIVER]: Failed to load {0} assets", failedAssetRestores); m_errorMessage += String.Format("Failed to load {0} assets", failedAssetRestores); } } foreach (DearchiveContext sceneContext in sceneContexts.Values) { 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<IEstateModule>(); 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<UUID>(), m_errorMessage); return; } } // 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("[ARCHIVER]: 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_rootScene.EventManager.TriggerOarFileLoaded(m_requestId, dearchivedScenes.GetLoadedScenes(), m_errorMessage); }