/// <summary>
        /// Execute the request
        /// </summary>
        /// <remarks>
        /// Only call this once.  To load another IAR, construct another request object.
        /// </remarks>
        /// <returns>
        /// A list of the inventory nodes loaded.  If folders were loaded then only the root folders are
        /// returned
        /// </returns>
        /// <exception cref="System.Exception">Thrown if load fails.</exception>
        public HashSet<InventoryNodeBase> Execute()
        {
            try
            {
                string filePath = "ERROR";
               
                List<InventoryFolderBase> folderCandidates
                    = InventoryArchiveUtils.FindFolderByPath(
                        m_scene.InventoryService, m_userInfo.PrincipalID, m_invPath);
    
                if (folderCandidates.Count == 0)
                {
                    // Possibly provide an option later on to automatically create this folder if it does not exist
                    m_log.ErrorFormat("[INVENTORY ARCHIVER]: Inventory path {0} does not exist", m_invPath);
    
                    return m_loadedNodes;
                }
                
                m_rootDestinationFolder = folderCandidates[0];
                archive = new TarArchiveReader(m_loadStream);
                byte[] data;
                TarArchiveReader.TarEntryType entryType;

                while ((data = archive.ReadEntry(out filePath, out entryType)) != null)
                {
                    if (filePath == ArchiveConstants.CONTROL_FILE_PATH)
                    {
                        LoadControlFile(filePath, data);
                    }                    
                    else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH))
                    {
                        LoadAssetFile(filePath, data);
                    }
                    else if (filePath.StartsWith(ArchiveConstants.INVENTORY_PATH))
                    {
                        LoadInventoryFile(filePath, entryType, data);
                    }
                }
                
                archive.Close();
                
                m_log.DebugFormat(
                    "[INVENTORY ARCHIVER]: Successfully loaded {0} assets with {1} failures", 
                    m_successfulAssetRestores, m_failedAssetRestores);
                m_log.InfoFormat("[INVENTORY ARCHIVER]: Successfully loaded {0} items", m_successfulItemRestores);
                
                return m_loadedNodes;
            }
            finally
            {
                m_loadStream.Close();
            }
        }
Example #2
0
        public void LoadRegionBackup(TarArchiveReader reader, IScene scene)
        {
            IAuroraBackupModule[] modules = scene.RequestModuleInterfaces<IAuroraBackupModule>();

            byte[] data;
            string filePath;
            TarArchiveReader.TarEntryType entryType;

            foreach (IAuroraBackupModule module in modules)
                module.BeginLoadModuleFromArchive(scene);

            while ((data = reader.ReadEntry(out filePath, out entryType)) != null)
            {
                if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType)
                    continue;
                foreach (IAuroraBackupModule module in modules)
                    module.LoadModuleFromArchive(data, filePath, entryType, scene);
            }

            reader.Close();

            foreach (IAuroraBackupModule module in modules)
                module.EndLoadModuleFromArchive(scene);
        }
        private void DearchiveRegion0DotStar()
        {
            int successfulAssetRestores = 0;
            int failedAssetRestores = 0;
            //List<string> serialisedSceneObjects = new List<string>();
            List<string> serialisedParcels = new List<string>();
            string filePath = "NONE";
            DateTime start = DateTime.Now;

            TarArchiveReader archive = new TarArchiveReader(m_loadStream);
            byte[] data;
            TarArchiveReader.TarEntryType entryType;

            if (!m_skipAssets)
                m_threadpool = new Aurora.Framework.AuroraThreadPool(new Aurora.Framework.AuroraThreadPoolStartInfo()
                    {
                        Threads = 1,
                        priority = System.Threading.ThreadPriority.BelowNormal
                    });
            
            IBackupModule backup = m_scene.RequestModuleInterface<IBackupModule>();
            if (!m_merge)
            {
                DateTime before = DateTime.Now;
                m_log.Info("[ARCHIVER]: Clearing all existing scene objects");
                if (backup != null)
                    backup.DeleteAllSceneObjects();
                m_log.Info("[ARCHIVER]: Cleared all existing scene objects in " + (DateTime.Now - before).Minutes + ":" + (DateTime.Now - before).Seconds);
            }

            IScriptModule[] modules = m_scene.RequestModuleInterfaces<IScriptModule>();
            //Disable the script engine so that it doesn't load in the background and kill OAR loading
            foreach (IScriptModule module in modules)
            {
                module.Disabled = true;
            }
            //Disable backup for now as well
            if (backup != null)
                backup.LoadingPrims = true;

            IRegionSerialiserModule serialiser = m_scene.RequestModuleInterface<IRegionSerialiserModule>();
            int sceneObjectsLoadedCount = 0;

            //We save the groups so that we can back them up later
            List<SceneObjectGroup> groupsToBackup = new List<SceneObjectGroup>();

            try
            {
                while ((data = archive.ReadEntry(out filePath, out entryType)) != null)
                {
                    //m_log.DebugFormat(
                    //    "[ARCHIVER]: Successfully read {0} ({1} bytes)", filePath, data.Length);

                    if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType)
                        continue;

                    if (filePath.StartsWith(ArchiveConstants.OBJECTS_PATH))
                    {
                        /*
                        m_log.DebugFormat("[ARCHIVER]: Loading xml with raw size {0}", serialisedSceneObject.Length);

                        // Really large xml files (multi megabyte) appear to cause
                        // memory problems
                        // when loading the xml.  But don't enable this check yet
                
                        if (serialisedSceneObject.Length > 5000000)
                        {
                            m_log.Error("[ARCHIVER]: Ignoring xml since size > 5000000);");
                            continue;
                        }
                        */

                        SceneObjectGroup sceneObject = (SceneObjectGroup)serialiser.DeserializeGroupFromXml2 (data, m_scene);

                        if (sceneObject == null)
                        {
                            //! big error!
                            m_log.Error("Error reading SOP XML (Please mantis this!): " + m_asciiEncoding.GetString(data));
                            continue;
                        }
                        
                        foreach (SceneObjectPart part in sceneObject.ChildrenList)
                        {
                            if (!ResolveUserUuid(part.CreatorID))
                                part.CreatorID = m_scene.RegionInfo.EstateSettings.EstateOwner;

                            if (!ResolveUserUuid(part.OwnerID))
                                part.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;

                            if (!ResolveUserUuid(part.LastOwnerID))
                                part.LastOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;

                            // And zap any troublesome sit target information
                            part.SitTargetOrientation = new Quaternion(0, 0, 0, 1);
                            part.SitTargetPosition = new Vector3(0, 0, 0);

                            // Fix ownership/creator of inventory items
                            // Not doing so results in inventory items
                            // being no copy/no mod for everyone
                            lock (part.TaskInventory)
                            {
                                TaskInventoryDictionary inv = part.TaskInventory;
                                foreach (KeyValuePair<UUID, TaskInventoryItem> kvp in inv)
                                {
                                    if (!ResolveUserUuid(kvp.Value.OwnerID))
                                    {
                                        kvp.Value.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
                                    }
                                    if (!ResolveUserUuid(kvp.Value.CreatorID))
                                    {
                                        kvp.Value.CreatorID = m_scene.RegionInfo.EstateSettings.EstateOwner;
                                    }
                                }
                            }
                        }

                        //Add the offsets of the region
                        Vector3 newPos = new Vector3(sceneObject.AbsolutePosition.X + m_offsetX,
                            sceneObject.AbsolutePosition.Y + m_offsetY,
                            sceneObject.AbsolutePosition.Z + m_offsetZ);
                        if (m_flipX)
                            newPos.X = m_scene.RegionInfo.RegionSizeX - newPos.X;
                        if (m_flipY)
                            newPos.Y = m_scene.RegionInfo.RegionSizeY - newPos.Y;
                        sceneObject.SetAbsolutePosition(false, newPos);

                        if (m_scene.SceneGraph.AddPrimToScene(sceneObject))
                        {
                            groupsToBackup.Add(sceneObject);
                            sceneObject.ScheduleGroupUpdate (PrimUpdateFlags.ForcedFullUpdate);
                            sceneObjectsLoadedCount++;
                            sceneObject.CreateScriptInstances(0, false, 0, UUID.Zero);
                            sceneObject.ResumeScripts();
                        }
                        sceneObjectsLoadedCount++;
                        if (sceneObjectsLoadedCount % 250 == 0)
                            m_log.Info("[ARCHIVER]: Loaded " + sceneObjectsLoadedCount + " objects...");
                    }
                    else if (!m_skipAssets && filePath.StartsWith (ArchiveConstants.ASSETS_PATH))
                    {
                        if (LoadAsset (filePath, data))
                            successfulAssetRestores++;
                        else
                            failedAssetRestores++;

                        if ((successfulAssetRestores + failedAssetRestores) % 250 == 0)
                            m_log.Info ("[ARCHIVER]: Loaded " + successfulAssetRestores + " assets and failed to load " + failedAssetRestores + " assets...");
                    }
                    else if (filePath.StartsWith (ArchiveConstants.TERRAINS_PATH))
                    {
                        LoadTerrain (filePath, data);
                    }
                    else if (!m_merge && filePath.StartsWith (ArchiveConstants.SETTINGS_PATH))
                    {
                        LoadRegionSettings (filePath, data);
                    }
                    else if (!m_merge && filePath.StartsWith (ArchiveConstants.LANDDATA_PATH))
                    {
                        serialisedParcels.Add (m_utf8Encoding.GetString (data));
                    }
                    else if (filePath == ArchiveConstants.CONTROL_FILE_PATH)
                    {
                        LoadControlFile (filePath, data);
                    }
                    else
                    {
                        m_log.Debug ("[ARCHIVER]:UNKNOWN PATH: " + filePath);
                    }
                }

                //m_log.Debug("[ARCHIVER]: Reached end of archive");
            }
            catch (Exception e)
            {
                m_log.ErrorFormat(
                    "[ARCHIVER]: Aborting load with error in archive file {0}.  {1}", filePath, e);
                m_errorMessage += e.ToString();
                m_scene.EventManager.TriggerOarFileLoaded(UUID.Zero.Guid, m_errorMessage);
                return;
            }
            finally
            {
                archive.Close();
                m_loadStream.Close();
                m_loadStream.Dispose ();

                //Reeanble now that we are done
                foreach (IScriptModule module in modules)
                {
                    module.Disabled = false;
                }
                //Reset backup too
                if (backup != null)
                    backup.LoadingPrims = false;
            }

            //Now back up the prims
            foreach (SceneObjectGroup grp in groupsToBackup)
            {
                //Backup!
                grp.HasGroupChanged = true;
            }

            if (!m_skipAssets)
            {
                if (m_useAsync && !AssetSaverIsRunning)
                    m_threadpool.QueueEvent(SaveAssets, 0);
                else if (!AssetSaverIsRunning)
                    SaveAssets();
            }

            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);
                }
            }

            // Try to retain the original creator/owner/lastowner if their uuid is present on this grid
            // otherwise, use the master avatar uuid instead

            // Reload serialized parcels
            if (!m_merge)
            {
                m_log.InfoFormat ("[ARCHIVER]: Loading {0} parcels.  Please wait.", serialisedParcels.Count);
                List<LandData> landData = new List<LandData> ();
                foreach (string serialisedParcel in serialisedParcels)
                {
                    LandData parcel = LandDataSerializer.Deserialize (serialisedParcel);
                    if (!ResolveUserUuid (parcel.OwnerID))
                        parcel.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
                    landData.Add (parcel);
                }
                IParcelManagementModule parcelManagementModule = m_scene.RequestModuleInterface<IParcelManagementModule> ();
                if (parcelManagementModule != null)
                    parcelManagementModule.ClearAllParcels ();
                if (landData.Count > 0)
                {
                    m_scene.EventManager.TriggerIncomingLandDataFromStorage (landData);
                    //Update the database as well!
                    if (parcelManagementModule != null)
                    {
                        foreach (LandData parcel in landData)
                        {
                            parcelManagementModule.UpdateLandObject (parcel.LocalID, parcel);
                        }
                    }
                }
                else if (parcelManagementModule != null)
                    parcelManagementModule.ResetSimLandObjects ();

                m_log.InfoFormat ("[ARCHIVER]: Restored {0} parcels.", landData.Count);

                //Clean it out
                landData.Clear ();
                serialisedParcels.Clear ();
            }

            m_log.InfoFormat("[ARCHIVER]: Successfully loaded archive in " + (DateTime.Now - start).Minutes + ":" + (DateTime.Now - start).Seconds);

            m_validUserUuids.Clear();
            m_scene.EventManager.TriggerOarFileLoaded(UUID.Zero.Guid, m_errorMessage);
        }
        private void DearchiveRegion0DotStar()
        {
            int successfulAssetRestores = 0;
            int failedAssetRestores = 0;
            List<string> serialisedSceneObjects = new List<string>();
            List<string> serialisedParcels = new List<string>();
            string filePath = "NONE";

            TarArchiveReader archive = new TarArchiveReader(m_loadStream);
            byte[] data;
            TarArchiveReader.TarEntryType entryType;
            
            try
            {
                while ((data = archive.ReadEntry(out filePath, out entryType)) != null)
                {
                    //m_log.DebugFormat(
                    //    "[ARCHIVER]: Successfully read {0} ({1} bytes)", filePath, data.Length);
                    
                    if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType)
                        continue;

                    if (filePath.StartsWith(ArchiveConstants.OBJECTS_PATH))
                    {
                        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(filePath, data);
                    }
                    else if (!m_merge && filePath.StartsWith(ArchiveConstants.SETTINGS_PATH))
                    {
                        LoadRegionSettings(filePath, data);
                    } 
                    else if (!m_merge && filePath.StartsWith(ArchiveConstants.LANDDATA_PATH))
                    {
                        serialisedParcels.Add(Encoding.UTF8.GetString(data));
                    } 
                    else if (filePath == ArchiveConstants.CONTROL_FILE_PATH)
                    {
                        LoadControlFile(filePath, data);
                    }
                }

                //m_log.Debug("[ARCHIVER]: Reached end of archive");
            }
            catch (Exception e)
            {
                m_log.ErrorFormat(
                    "[ARCHIVER]: Aborting load with error in archive file {0}.  {1}", filePath, e);
                m_errorMessage += e.ToString();
                m_scene.EventManager.TriggerOarFileLoaded(m_requestId, m_errorMessage);
                return;
            }
            finally
            {
                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);
                }
            }

            if (!m_merge)
            {
                m_log.Info("[ARCHIVER]: Clearing all existing scene objects");
                m_scene.DeleteAllSceneObjects();
            }

            // Try to retain the original creator/owner/lastowner if their uuid is present on this grid
            // otherwise, use the master avatar uuid instead

            // Reload serialized parcels
            m_log.InfoFormat("[ARCHIVER]: Loading {0} parcels.  Please wait.", serialisedParcels.Count);
            List<LandData> landData = new List<LandData>();
            foreach (string serialisedParcel in serialisedParcels)
            {
                LandData parcel = LandDataSerializer.Deserialize(serialisedParcel);
                if (!ResolveUserUuid(parcel.OwnerID))
                    parcel.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
                landData.Add(parcel);
            }
            m_scene.EventManager.TriggerIncomingLandDataFromStorage(landData);
            m_log.InfoFormat("[ARCHIVER]: Restored {0} parcels.", landData.Count);

            // Reload serialized prims
            m_log.InfoFormat("[ARCHIVER]: Loading {0} scene objects.  Please wait.", serialisedSceneObjects.Count);

            IRegionSerialiserModule serialiser = m_scene.RequestModuleInterface<IRegionSerialiserModule>();
            int sceneObjectsLoadedCount = 0;

            foreach (string serialisedSceneObject in serialisedSceneObjects)
            {
                /*
                m_log.DebugFormat("[ARCHIVER]: Loading xml with raw size {0}", serialisedSceneObject.Length);

                // Really large xml files (multi megabyte) appear to cause
                // memory problems
                // when loading the xml.  But don't enable this check yet
                
                if (serialisedSceneObject.Length > 5000000)
                {
                    m_log.Error("[ARCHIVER]: Ignoring xml since size > 5000000);");
                    continue;
                }
                */

                SceneObjectGroup sceneObject = serialiser.DeserializeGroupFromXml2(serialisedSceneObject);

                // 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
                // to the same scene (when this is possible).
                sceneObject.ResetIDs();

                foreach (SceneObjectPart part in sceneObject.Parts)
                {
                    if (!ResolveUserUuid(part.CreatorID))
                        part.CreatorID = m_scene.RegionInfo.EstateSettings.EstateOwner;

                    if (!ResolveUserUuid(part.OwnerID))
                        part.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;

                    if (!ResolveUserUuid(part.LastOwnerID))
                        part.LastOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;

                    // And zap any troublesome sit target information
                    part.SitTargetOrientation = new Quaternion(0, 0, 0, 1);
                    part.SitTargetPosition    = new Vector3(0, 0, 0);

                    // Fix ownership/creator of inventory items
                    // Not doing so results in inventory items
                    // being no copy/no mod for everyone
                    lock (part.TaskInventory)
                    {
                        TaskInventoryDictionary inv = part.TaskInventory;
                        foreach (KeyValuePair<UUID, TaskInventoryItem> kvp in inv)
                        {
                            if (!ResolveUserUuid(kvp.Value.OwnerID))
                            {
                                kvp.Value.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
                            }
                            if (!ResolveUserUuid(kvp.Value.CreatorID))
                            {
                                kvp.Value.CreatorID = m_scene.RegionInfo.EstateSettings.EstateOwner;
                            }
                        }
                    }
                }

                if (m_scene.AddRestoredSceneObject(sceneObject, true, false))
                {
                    sceneObjectsLoadedCount++;
                    sceneObject.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, 0);
                    sceneObject.ResumeScripts();
                }
            }

            m_log.InfoFormat("[ARCHIVER]: Restored {0} scene objects to the scene", sceneObjectsLoadedCount);

            int ignoredObjects = serialisedSceneObjects.Count - sceneObjectsLoadedCount;

            if (ignoredObjects > 0)
                m_log.WarnFormat("[ARCHIVER]: Ignored {0} scene objects that already existed in the scene", ignoredObjects);

            m_log.InfoFormat("[ARCHIVER]: Successfully loaded archive");

            m_scene.EventManager.TriggerOarFileLoaded(m_requestId, m_errorMessage);
        }
Example #5
0
        /// <summary>
        /// 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.
        /// </summary>
        /// <remarks>
        /// 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.
        /// </remarks>
        /// <param name="archive"></param>
        /// <param name="dearchivedScenes"></param>
        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");
        }
        private void DearchiveRegion0DotStar()
        {
            int successfulAssetRestores = 0;
            int failedAssetRestores = 0;
            List<string> serialisedSceneObjects = new List<string>();
            List<string> serialisedParcels = new List<string>();
            string filePath = "NONE";

            TarArchiveReader archive = new TarArchiveReader(m_loadStream);
            byte[] data;
            TarArchiveReader.TarEntryType entryType;
            
            try
            {
                while ((data = archive.ReadEntry(out filePath, out entryType)) != null)
                {
                    //m_log.DebugFormat(
                    //    "[ARCHIVER]: Successfully read {0} ({1} bytes)", filePath, data.Length);
                    
                    if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType)
                        continue;

                    if (filePath.StartsWith(ArchiveConstants.OBJECTS_PATH))
                    {
                        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(filePath, data);
                    }
                    else if (!m_merge && filePath.StartsWith(ArchiveConstants.SETTINGS_PATH))
                    {
                        LoadRegionSettings(filePath, data);
                    } 
                    else if (!m_merge && filePath.StartsWith(ArchiveConstants.LANDDATA_PATH))
                    {
                        serialisedParcels.Add(Encoding.UTF8.GetString(data));
                    } 
                    else if (filePath == ArchiveConstants.CONTROL_FILE_PATH)
                    {
                        LoadControlFile(filePath, data);
                    }
                }

                //m_log.Debug("[ARCHIVER]: Reached end of archive");
            }
            catch (Exception e)
            {
                m_log.ErrorFormat(
                    "[ARCHIVER]: Aborting load with error in archive file {0}.  {1}", filePath, e);
                m_errorMessage += e.ToString();
                m_scene.EventManager.TriggerOarFileLoaded(m_requestId, m_errorMessage);
                return;
            }
            finally
            {
                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);
                }
            }

            if (!m_merge)
            {
                m_log.Info("[ARCHIVER]: Clearing all existing scene objects");
                m_scene.DeleteAllSceneObjects();
            }

            LoadParcels(serialisedParcels);
            LoadObjects(serialisedSceneObjects);

            m_log.InfoFormat("[ARCHIVER]: Successfully loaded archive");

            m_scene.EventManager.TriggerOarFileLoaded(m_requestId, m_errorMessage);
        }
        /// <summary>
        /// Execute the request
        /// </summary>
        /// <returns>
        /// A list of the inventory nodes loaded.  If folders were loaded then only the root folders are
        /// returned
        /// </returns>
        public List<InventoryNodeBase> Execute()
        {
            string filePath = "ERROR";
            int successfulAssetRestores = 0;
            int failedAssetRestores = 0;
            int successfulItemRestores = 0;
            List<InventoryNodeBase> nodesLoaded = new List<InventoryNodeBase>();

            if (!m_userInfo.HasReceivedInventory)
            {
                // If the region server has access to the user admin service (by which users are created),
                // then we'll assume that it's okay to fiddle with the user's inventory even if they are not on the
                // server.
                //
                // FIXME: FetchInventory should probably be assumed to by async anyway, since even standalones might
                // use a remote inventory service, though this is vanishingly rare at the moment.
                if (null == m_commsManager.UserAdminService)
                {
                    m_log.ErrorFormat(
                        "[INVENTORY ARCHIVER]: Have not yet received inventory info for user {0} {1}",
                        m_userInfo.UserProfile.Name, m_userInfo.UserProfile.ID);

                    return nodesLoaded;
                }
                else
                {
                    m_userInfo.FetchInventory();
                    for (int i = 0 ; i < 50 ; i++)
                    {
                        if (m_userInfo.HasReceivedInventory == true)
                            break;
                        Thread.Sleep(200);
                    }
                }
            }

            InventoryFolderImpl rootDestinationFolder = m_userInfo.RootFolder.FindFolderByPath(m_invPath);

            if (null == rootDestinationFolder)
            {
                // Possibly provide an option later on to automatically create this folder if it does not exist
                m_log.ErrorFormat("[INVENTORY ARCHIVER]: Inventory path {0} does not exist", m_invPath);

                return nodesLoaded;
            }

            archive = new TarArchiveReader(m_loadStream);

            // In order to load identically named folders, we need to keep track of the folders that we have already
            // created
            Dictionary <string, InventoryFolderImpl> foldersCreated = new Dictionary<string, InventoryFolderImpl>();

            byte[] data;
            TarArchiveReader.TarEntryType entryType;
            while ((data = archive.ReadEntry(out filePath, out entryType)) != null)
            {
                if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH))
                {
                    if (LoadAsset(filePath, data))
                        successfulAssetRestores++;
                    else
                        failedAssetRestores++;
                }
                else if (filePath.StartsWith(ArchiveConstants.INVENTORY_PATH))
                {
                    InventoryFolderImpl foundFolder 
                        = ReplicateArchivePathToUserInventory(
                            filePath, TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType, 
                            rootDestinationFolder, foldersCreated, nodesLoaded);

                    if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY != entryType)
                    {
                        InventoryItemBase item = UserInventoryItemSerializer.Deserialize(data);
                        
                        // Don't use the item ID that's in the file
                        item.ID = UUID.Random();

                        UUID ospResolvedId = OspResolver.ResolveOspa(item.CreatorId, m_commsManager); 
                        if (UUID.Zero != ospResolvedId)
                            item.CreatorIdAsUuid = ospResolvedId;
                        
                        item.Owner = m_userInfo.UserProfile.ID;

                        // Reset folder ID to the one in which we want to load it
                        item.Folder = foundFolder.ID;

                        m_userInfo.AddItem(item);
                        successfulItemRestores++;

                        // If we're loading an item directly into the given destination folder then we need to record
                        // it separately from any loaded root folders
                        if (rootDestinationFolder == foundFolder)
                            nodesLoaded.Add(item);
                    }
                }
            }

            archive.Close();

            m_log.DebugFormat("[INVENTORY ARCHIVER]: Restored {0} assets", successfulAssetRestores);
            m_log.InfoFormat("[INVENTORY ARCHIVER]: Restored {0} items", successfulItemRestores);

            return nodesLoaded;
        }
        /// <summary>
        /// Execute the request
        /// </summary>
        /// <returns>
        /// A list of the inventory nodes loaded.  If folders were loaded then only the root folders are
        /// returned
        /// </returns>
        public HashSet<InventoryNodeBase> Execute(bool loadAll)
        {
            try
            {
                string filePath = "ERROR";
                int successfulAssetRestores = 0;
                int failedAssetRestores = 0;
                int successfulItemRestores = 0;

                HashSet<InventoryNodeBase> loadedNodes = new HashSet<InventoryNodeBase>();
               
                List<InventoryFolderBase> folderCandidates
                    = InventoryArchiveUtils.FindFolderByPath(
                        m_registry.RequestModuleInterface<IInventoryService>(), m_userInfo.PrincipalID, m_invPath);
    
                if (folderCandidates.Count == 0)
                {
                    // Possibly provide an option later on to automatically create this folder if it does not exist
                    m_log.ErrorFormat("[INVENTORY ARCHIVER]: Inventory path {0} does not exist", m_invPath);
    
                    return loadedNodes;
                }
                
                InventoryFolderBase rootDestinationFolder = folderCandidates[0];
                archive = new TarArchiveReader(m_loadStream);
    
                // In order to load identically named folders, we need to keep track of the folders that we have already
                // resolved
                Dictionary <string, InventoryFolderBase> resolvedFolders = new Dictionary<string, InventoryFolderBase>();
    
                byte[] data;
                TarArchiveReader.TarEntryType entryType;

                while ((data = archive.ReadEntry(out filePath, out entryType)) != null)
                {
                    if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH))
                    {
                        if (LoadAsset(filePath, data))
                            successfulAssetRestores++;
                        else
                            failedAssetRestores++;
    
                        if ((successfulAssetRestores) % 50 == 0)
                            m_log.DebugFormat(
                                "[INVENTORY ARCHIVER]: Loaded {0} assets...", 
                                successfulAssetRestores);
                    }
                    else if (filePath.StartsWith(ArchiveConstants.INVENTORY_PATH))
                    {
                        filePath = filePath.Substring(ArchiveConstants.INVENTORY_PATH.Length);
                        
                        // Trim off the file portion if we aren't already dealing with a directory path
                        if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY != entryType)
                            filePath = filePath.Remove(filePath.LastIndexOf("/") + 1);
                        
                        InventoryFolderBase foundFolder 
                            = ReplicateArchivePathToUserInventory(
                                filePath, rootDestinationFolder, resolvedFolders, loadedNodes);
    
                        if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY != entryType)
                        {
                            InventoryItemBase item = LoadItem(data, foundFolder);
    
                            if (item != null)
                            {
                                successfulItemRestores++;
                                
                                // If we aren't loading the folder containing the item then well need to update the 
                                // viewer separately for that item.
                                if (!loadedNodes.Contains(foundFolder))
                                {
                                    if (loadAll)
                                        loadedNodes.Add(item);
                                }
                            }
                        }
                    }
                }
                
                archive.Close();
                
                m_log.DebugFormat(
                    "[INVENTORY ARCHIVER]: Successfully loaded {0} assets with {1} failures", 
                    successfulAssetRestores, failedAssetRestores);
                m_log.InfoFormat("[INVENTORY ARCHIVER]: Successfully loaded {0} items", successfulItemRestores);
                
                return loadedNodes;
            }
            finally
            {
                m_loadStream.Close();
            }
        }
        /// <summary>
        /// Execute the request
        /// </summary>
        /// <returns>
        /// A list of the inventory nodes loaded.  If folders were loaded then only the root folders are
        /// returned
        /// </returns>
        public List<InventoryNodeBase> Execute()
        {
            string filePath = "ERROR";
            int successfulAssetRestores = 0;
            int failedAssetRestores = 0;
            int successfulItemRestores = 0;
            List<InventoryNodeBase> nodesLoaded = new List<InventoryNodeBase>();
           
            //InventoryFolderImpl rootDestinationFolder = m_userInfo.RootFolder.FindFolderByPath(m_invPath);
            InventoryFolderBase rootDestinationFolder 
                = InventoryArchiveUtils.FindFolderByPath(
                    m_scene.InventoryService, m_userInfo.UserProfile.ID, m_invPath);

            if (null == rootDestinationFolder)
            {
                // Possibly provide an option later on to automatically create this folder if it does not exist
                m_log.ErrorFormat("[INVENTORY ARCHIVER]: Inventory path {0} does not exist", m_invPath);

                return nodesLoaded;
            }

            archive = new TarArchiveReader(m_loadStream);

            // In order to load identically named folders, we need to keep track of the folders that we have already
            // created
            Dictionary <string, InventoryFolderBase> foldersCreated = new Dictionary<string, InventoryFolderBase>();

            byte[] data;
            TarArchiveReader.TarEntryType entryType;

            try
            {
                while ((data = archive.ReadEntry(out filePath, out entryType)) != null)
                {
                    if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH))
                    {
                        if (LoadAsset(filePath, data))
                            successfulAssetRestores++;
                        else
                            failedAssetRestores++;
    
                        if ((successfulAssetRestores) % 50 == 0)
                            m_log.DebugFormat(
                                "[INVENTORY ARCHIVER]: Loaded {0} assets...", 
                                successfulAssetRestores);
                    }
                    else if (filePath.StartsWith(ArchiveConstants.INVENTORY_PATH))
                    {
                        InventoryFolderBase foundFolder 
                            = ReplicateArchivePathToUserInventory(
                                filePath, TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType, 
                                rootDestinationFolder, foldersCreated, nodesLoaded);
    
                        if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY != entryType)
                        {
                            InventoryItemBase item = LoadItem(data, foundFolder);
    
                            if (item != null)
                            {
                                successfulItemRestores++;
                                
                                // If we're loading an item directly into the given destination folder then we need to record
                                // it separately from any loaded root folders
                                if (rootDestinationFolder == foundFolder)
                                    nodesLoaded.Add(item);
                            }
                        }
                    }
                }
            }
            finally
            {
                archive.Close();
            }

            m_log.DebugFormat(
                "[INVENTORY ARCHIVER]: Successfully loaded {0} assets with {1} failures", 
                successfulAssetRestores, failedAssetRestores);
            m_log.InfoFormat("[INVENTORY ARCHIVER]: Successfully loaded {0} items", successfulItemRestores);

            return nodesLoaded;
        }
Example #10
0
        private void DearchiveRegion0DotStar()
        {
            int successfulAssetRestores = 0;
            int failedAssetRestores = 0;
            List<string> serializedSceneObjects = new List<string>();
            string filePath = "NONE";
            
            try
            {
                TarArchiveReader archive = new TarArchiveReader(m_loadStream);
               
                byte[] data;
                TarArchiveReader.TarEntryType entryType;

                while ((data = archive.ReadEntry(out filePath, out entryType)) != null)
                {                    
                    //m_log.DebugFormat(
                    //    "[ARCHIVER]: Successfully read {0} ({1} bytes)", filePath, data.Length);
                    
                    if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType)
                        continue;                    

                    if (filePath.StartsWith(ArchiveConstants.OBJECTS_PATH))
                    {
                        serializedSceneObjects.Add(Encoding.UTF8.GetString(data));
                    }
                    else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH))
                    {
                        if (LoadAsset(filePath, data))
                            successfulAssetRestores++;
                        else
                            failedAssetRestores++;
                    }
                    else if (!m_merge && filePath.StartsWith(ArchiveConstants.TERRAINS_PATH))
                    {
                        LoadTerrain(filePath, data);
                    }
                    else if (!m_merge && filePath.StartsWith(ArchiveConstants.SETTINGS_PATH))
                    {
                        LoadRegionSettings(filePath, data);
                    }
                }

                //m_log.Debug("[ARCHIVER]: Reached end of archive");

                archive.Close();
            }
            catch (Exception e)
            {
                m_log.ErrorFormat(
                    "[ARCHIVER]: Aborting load with error in archive file {0}.  {1}", filePath, e);
                m_errorMessage += e.ToString();
                m_scene.EventManager.TriggerOarFileLoaded(m_requestId, m_errorMessage);
                return;
            }

            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);
            }

            // Reload serialized prims
            m_log.InfoFormat("[ARCHIVER]: Preparing {0} scene objects.  Please wait.", serializedSceneObjects.Count);

            IRegionSerializerModule serializer = m_scene.RequestModuleInterface<IRegionSerializerModule>();
            int sceneObjectsLoadedCount = 0;

            List<SceneObjectGroup> backupObjects = new List<SceneObjectGroup>();
            Dictionary<UUID, UUID> OriginalBackupIDs = new Dictionary<UUID, UUID>();

            bool objectFixingFailed = false;

            foreach (string serializedSceneObject in serializedSceneObjects)
            {
                SceneObjectGroup sceneObject;
                try
                {
                    sceneObject = serializer.DeserializeGroupFromXml2(serializedSceneObject);
                }
                catch (Exception e)
                {
                    m_log.InfoFormat("[ARCHIVER]: Error while deserializing group: {0}", e);
                    if (m_skipErrorGroups) continue;
                    else throw;
                }

                if (sceneObject == null)
                {
                    if (m_skipErrorGroups) continue;
                    else throw new Exception("Error while deserializing group");
                }

                // 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
                // to the same scene (when this is possible).
                UUID OldUUID = sceneObject.UUID;
                sceneObject.ResetIDs();
                // if sceneObject is no-copy, save the old ID with the new ID.
                OriginalBackupIDs[sceneObject.UUID] = OldUUID;

                // Try to retain the original creator/owner/lastowner if their uuid is present on this grid
                // otherwise, use the master avatar uuid instead
                UUID masterAvatarId = m_scene.RegionInfo.MasterAvatarAssignedUUID;

                if (m_scene.RegionInfo.EstateSettings.EstateOwner != UUID.Zero)
                    masterAvatarId = m_scene.RegionInfo.EstateSettings.EstateOwner;

                foreach (SceneObjectPart part in sceneObject.GetParts())
                {
                    if (!ResolveUserUuid(part.CreatorID))
                    {
                        m_log.WarnFormat("[ARCHIVER]: Could not resolve av/group ID {0} for object '{1}' part creator", part.CreatorID, sceneObject.Name);
                        objectFixingFailed = true;
                        part.CreatorID = masterAvatarId;
                    }

                    if (!ResolveUserUuid(part.OwnerID))
                    {
                        m_log.WarnFormat("[ARCHIVER]: Could not resolve av/group ID {0} for object '{1}' part owner", part.OwnerID, sceneObject.Name);
                        objectFixingFailed = true;
                        part.OwnerID = masterAvatarId;
                    }

                    if (!ResolveUserUuid(part.LastOwnerID))
                    {
                        m_log.WarnFormat("[ARCHIVER]: Could not resolve av/group ID {0} for object '{1}' part last owner", part.LastOwnerID, sceneObject.Name);
                        objectFixingFailed = true;
                        part.LastOwnerID = masterAvatarId;
                    }


                    // Fix ownership/creator of inventory items
                    // Not doing so results in inventory items
                    // being no copy/no mod for everyone
                    lock (part.TaskInventory)
                    {
                        TaskInventoryDictionary inv = part.TaskInventory;
                        foreach (KeyValuePair<UUID, TaskInventoryItem> kvp in inv)
                        {
                            if (!ResolveUserUuid(kvp.Value.OwnerID))
                            {
                                m_log.WarnFormat("[ARCHIVER]: Could not resolve av/group ID {0} for object '{1}' inventory item owner", kvp.Value.OwnerID, sceneObject.Name);
                                objectFixingFailed = true;
                                kvp.Value.OwnerID = masterAvatarId;
                            }

                            if (!ResolveUserUuid(kvp.Value.CreatorID))
                            {
                                m_log.WarnFormat("[ARCHIVER]: Could not resolve av/group ID {0} for object '{1}' inventory item creator", kvp.Value.CreatorID, sceneObject.Name);
                                objectFixingFailed = true;
                                kvp.Value.CreatorID = masterAvatarId;
                            }
                        }
                    }
                }

                backupObjects.Add(sceneObject);
            }

            if (objectFixingFailed && !m_allowUserReassignment)
            {
                m_log.Error("[ARCHIVER]: Could not restore scene objects. One or more avatar accounts not found.");
                return;
            }

            Dictionary<UUID, SceneObjectGroup> ExistingNoCopyObjects = new Dictionary<UUID,SceneObjectGroup>();
            if (!m_merge)
            {
                m_log.Info("[ARCHIVER]: Clearing all existing scene objects");
                m_scene.DeleteAllSceneObjectsExcept(delegate(SceneObjectGroup existingSOG)
                                {   // Return true if this object should be skipped in the delete.

                                    // Don't delete any no-copy objects.
                                    if (NoCopyObjectOrContents(existingSOG)) 
                                    {
                                        ExistingNoCopyObjects.Add(existingSOG.UUID, existingSOG);
                                        return true;
                                    }
                                    return false;
                                });
            }

            m_log.InfoFormat("[ARCHIVER]: Loading {0} scene objects.  Please wait.", serializedSceneObjects.Count);

            // sceneObject is the one from backup to restore to the scene
            foreach (SceneObjectGroup backupObject in backupObjects)
            {
                SceneObjectGroup existingObject = null;
                UUID originalUUID = OriginalBackupIDs[backupObject.UUID];
                // Don't restore any no-copy objects unless there was an existing matching UUID in the scene.
                if (ExistingNoCopyObjects.ContainsKey(originalUUID))
                    existingObject = ExistingNoCopyObjects[originalUUID];
                // existingSOG here means existing NO-COPY object, not deleted from scene above

                if (NoCopyObjectOrContents(backupObject))
                {
                    if ((existingObject != null) && !existingObject.IsAttachment)
                    {
                        // copy only position and rotation from backup
                        existingObject.Rotation = backupObject.Rotation;
                        existingObject.AbsolutePosition = backupObject.AbsolutePosition;
                    }
                    // don't restore no-copy items
                }
                else
                if (m_scene.AddRestoredSceneObject(backupObject, true, false))
                {
                    // this may have added 2nd copyable copy if existingObject is no-copy
                    sceneObjectsLoadedCount++;
                    backupObject.CreateScriptInstances(0, ScriptStartFlags.PostOnRez, m_scene.DefaultScriptEngine, 0, null);
                }
            }

            m_log.InfoFormat("[ARCHIVER]: Restored {0} scene objects to the scene", sceneObjectsLoadedCount);

            int ignoredObjects = serializedSceneObjects.Count - sceneObjectsLoadedCount;

            if (ignoredObjects > 0)
                m_log.WarnFormat("[ARCHIVER]: Ignored {0} scene objects that already existed in the scene", ignoredObjects);

            m_log.InfoFormat("[ARCHIVER]: Successfully loaded archive");

            m_scene.EventManager.TriggerOarFileLoaded(m_requestId, m_errorMessage);
        }
        /// <summary>
        /// Execute the request
        /// </summary>
        /// <remarks>
        /// Only call this once.  To load another IAR, construct another request object.
        /// </remarks>
        /// <returns>
        /// A list of the inventory nodes loaded.  If folders were loaded then only the root folders are
        /// returned
        /// </returns>
        /// <exception cref="System.Exception">Thrown if load fails.</exception>
        public HashSet<InventoryNodeBase> Execute()
        {
            try
            {
                Exception reportedException = null;

                string filePath = "ERROR";
               
                List<InventoryFolderBase> folderCandidates
                    = InventoryArchiveUtils.FindFoldersByPath(
                        m_InventoryService, m_userInfo.PrincipalID, m_invPath);
    
                if (folderCandidates.Count == 0)
                {
                    // Possibly provide an option later on to automatically create this folder if it does not exist
                    m_log.ErrorFormat("[INVENTORY ARCHIVER]: Inventory path {0} does not exist", m_invPath);
    
                    return m_loadedNodes;
                }
                
                m_rootDestinationFolder = folderCandidates[0];
                archive = new TarArchiveReader(m_loadStream);
                byte[] data;
                TarArchiveReader.TarEntryType entryType;

                while ((data = archive.ReadEntry(out filePath, out entryType)) != null)
                {
                    if (filePath == ArchiveConstants.CONTROL_FILE_PATH)
                    {
                        LoadControlFile(filePath, data);
                    }                    
                    else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH))
                    {
                        LoadAssetFile(filePath, data);
                    }
                    else if (filePath.StartsWith(ArchiveConstants.INVENTORY_PATH))
                    {
                        LoadInventoryFile(filePath, entryType, data);
                    }
                }
                
                archive.Close();

                m_log.DebugFormat(
                    "[INVENTORY ARCHIVER]: Successfully loaded {0} assets with {1} failures", 
                    m_successfulAssetRestores, m_failedAssetRestores);

                //Alicia: When this is called by LibraryModule or Tests, m_module will be null as event is not required
                if(m_module != null)
                    m_module.TriggerInventoryArchiveLoaded(m_id, true, m_userInfo, m_invPath, m_loadStream, reportedException, m_successfulItemRestores);
                
                return m_loadedNodes;
            }
            catch(Exception Ex)
            {
                // Trigger saved event with failed result and exception data
                if (m_module != null)
                    m_module.TriggerInventoryArchiveLoaded(m_id, false, m_userInfo, m_invPath, m_loadStream, Ex, 0);

                return m_loadedNodes;
            }
            finally
            {
                m_loadStream.Close();
            }
        }