Beispiel #1
0
        /// <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);
        }