public void TestCorruptAsset()
        {
            TestHelpers.InMethod();

            UUID      corruptAssetUuid = UUID.Parse("00000000-0000-0000-0000-000000000666");
            AssetBase corruptAsset
                = AssetHelpers.CreateAsset(corruptAssetUuid, AssetType.Notecard, "CORRUPT ASSET", UUID.Zero);

            m_assetService.Store(corruptAsset);

            m_uuidGatherer.AddForInspection(corruptAssetUuid);
            m_uuidGatherer.GatherAll();

            // We count the uuid as gathered even if the asset itself is corrupt.
            Assert.That(m_uuidGatherer.GatheredUuids.Count, Is.EqualTo(1));
        }
Exemplo n.º 2
0
        /// -----------------------------------------------------------------
        /// <summary>
        /// </summary>
        // -----------------------------------------------------------------
        public ResponseBase GetDependentAssetsHandler(RequestBase irequest)
        {
            if (irequest.GetType() != typeof(GetDependentAssetsRequest))
            {
                return(OperationFailed("wrong type"));
            }

            GetDependentAssetsRequest request = (GetDependentAssetsRequest)irequest;
            AssetBase asset = m_cache.Get(request.AssetID.ToString());

            if (asset == null)
            {
                return(OperationFailed("no such asset"));
            }

            UuidGatherer gatherer = new UuidGatherer(m_scene.AssetService);

            gatherer.AddForInspection(request.AssetID);
            gatherer.GatherAll();

            Dictionary <UUID, sbyte> assetids = (Dictionary <UUID, sbyte>)gatherer.GatheredUuids;

            List <UUID> assets = new List <UUID>(assetids.Keys);

            return(new GetDependentAssetsResponse(assets));
        }
Exemplo n.º 3
0
        /// <summary>
        /// Iterates through all Scenes, doing a deep scan through assets
        /// to update the access time of all assets present in the scene or referenced by assets
        /// in the scene.
        /// </summary>
        /// <param name="storeUncached">
        /// If true, then assets scanned which are not found in cache are added to the cache.
        /// </param>
        /// <returns>Number of distinct asset references found in the scene.</returns>
        private int TouchAllSceneAssets(bool storeUncached)
        {
            UuidGatherer gatherer = new UuidGatherer(m_AssetService);

            HashSet <UUID> uniqueUuids = new HashSet <UUID>();

            m_Scenes.ForEach(delegate(Scene s)
            {
                StampRegionStatusFile(s.RegionInfo.RegionID);

                s.ForEachSOG(delegate(SceneObjectGroup e)
                {
                    gatherer.AddForInspection(e);
                    gatherer.GatherAll();
                    IDictionary <UUID, sbyte> assets = gatherer.GatheredUuids;

                    foreach (UUID assetID in assets.Keys)
                    {
                        string filename = GetFileName(assetID.ToString());

                        if (File.Exists(filename))
                        {
                            if (!uniqueUuids.Contains(assetID))
                            {
                                File.SetLastAccessTime(filename, DateTime.Now);
                            }
                        }
                        else if (storeUncached)
                        {
                            AssetBase cachedAsset = null;
                            if (!uniqueUuids.Contains(assetID))
                            {
                                cachedAsset = m_AssetService.Get(assetID.ToString());
                            }
                            if (cachedAsset == null && assets[assetID] != (sbyte)AssetType.Unknown)
                            {
                                m_log.DebugFormat(
                                    "[FLOTSAM ASSET CACHE]: Could not find asset {0}, type {1} referenced by object {2} at {3} in scene {4} when pre-caching all scene assets",
                                    assetID, assets[assetID], e.Name, e.AbsolutePosition, s.Name);
                            }
                        }

                        uniqueUuids.Add(assetID);
                    }

                    assets.Clear();
                });
            });


            return(uniqueUuids.Count);
        }
        /// <summary>
        /// Iterates through all Scenes, doing a deep scan through assets
        /// to update the access time of all assets present in the scene or referenced by assets
        /// in the scene.
        /// </summary>
        /// <param name="storeUncached">
        /// If true, then assets scanned which are not found in cache are added to the cache.
        /// </param>
        /// <returns>Number of distinct asset references found in the scene.</returns>
        private int TouchAllSceneAssets(bool storeUncached)
        {
            UuidGatherer gatherer = new UuidGatherer(m_AssetService);

            Dictionary <UUID, bool> assetsFound = new Dictionary <UUID, bool>();

            foreach (Scene s in m_Scenes)
            {
                StampRegionStatusFile(s.RegionInfo.RegionID);

                s.ForEachSOG(delegate(SceneObjectGroup e)
                {
                    gatherer.AddForInspection(e);
                    gatherer.GatherAll();

                    foreach (UUID assetID in gatherer.GatheredUuids.Keys)
                    {
                        if (!assetsFound.ContainsKey(assetID))
                        {
                            string filename = GetFileName(assetID.ToString());

                            if (File.Exists(filename))
                            {
                                UpdateFileLastAccessTime(filename);
                            }
                            else if (storeUncached)
                            {
                                AssetBase cachedAsset = m_AssetService.Get(assetID.ToString());
                                if (cachedAsset == null && gatherer.GatheredUuids[assetID] != (sbyte)AssetType.Unknown)
                                {
                                    assetsFound[assetID] = false;
                                }
                                else
                                {
                                    assetsFound[assetID] = true;
                                }
                            }
                        }
                        else if (!assetsFound[assetID])
                        {
                            m_log.DebugFormat(
                                "[FLOTSAM ASSET CACHE]: Could not find asset {0}, type {1} referenced by object {2} at {3} in scene {4} when pre-caching all scene assets",
                                assetID, gatherer.GatheredUuids[assetID], e.Name, e.AbsolutePosition, s.Name);
                        }
                    }

                    gatherer.GatheredUuids.Clear();
                });
            }

            return(assetsFound.Count);
        }
        private void ArchiveOneRegion(Scene scene, string regionDir, Dictionary <UUID, sbyte> assetUuids,
                                      HashSet <UUID> failedIDs, HashSet <UUID> uncertainAssetsUUIDs)
        {
            m_log.InfoFormat("[ARCHIVER]: Writing region {0}", scene.Name);

            EntityBase[]            entities     = scene.GetEntities();
            List <SceneObjectGroup> sceneObjects = new List <SceneObjectGroup>();

            int numObjectsSkippedPermissions = 0;

            // Filter entities so that we only have scene objects.
            // FIXME: Would be nicer to have this as a proper list in SceneGraph, since lots of methods
            // end up having to do this
            IPermissionsModule permissionsModule = scene.RequestModuleInterface <IPermissionsModule>();

            foreach (EntityBase entity in entities)
            {
                if (entity is SceneObjectGroup)
                {
                    SceneObjectGroup sceneObject = entity as SceneObjectGroup;

                    if (!sceneObject.IsDeleted && !sceneObject.IsAttachment && !sceneObject.IsTemporary && !sceneObject.inTransit)
                    {
                        if (!CanUserArchiveObject(scene.RegionInfo.EstateSettings.EstateOwner, sceneObject, FilterContent, permissionsModule))
                        {
                            // The user isn't allowed to copy/transfer this object, so it will not be included in the OAR.
                            ++numObjectsSkippedPermissions;
                        }
                        else
                        {
                            sceneObjects.Add(sceneObject);
                        }
                    }
                }
            }

            if (SaveAssets)
            {
                UuidGatherer assetGatherer = new UuidGatherer(scene.AssetService, assetUuids, failedIDs, uncertainAssetsUUIDs);
                int          prevAssets    = assetUuids.Count;

                foreach (SceneObjectGroup sceneObject in sceneObjects)
                {
                    int curErrorCntr = assetGatherer.ErrorCount;
                    int possible     = assetGatherer.possibleNotAssetCount;
                    assetGatherer.AddForInspection(sceneObject);
                    assetGatherer.GatherAll();
                    curErrorCntr = assetGatherer.ErrorCount - curErrorCntr;
                    possible     = assetGatherer.possibleNotAssetCount - possible;
                    if (curErrorCntr > 0)
                    {
                        m_log.ErrorFormat("[ARCHIVER]: object {0} '{1}', at {2}, contains {3} references to missing or damaged assets",
                                          sceneObject.UUID, sceneObject.Name, sceneObject.AbsolutePosition.ToString(), curErrorCntr);
                        if (possible > 0)
                        {
                            m_log.WarnFormat("[ARCHIVER Warning]: object also contains {0} references that may not be assets or are missing", possible);
                        }
                    }
                    else if (possible > 0)
                    {
                        m_log.WarnFormat("[ARCHIVER Warning]: object {0} '{1}', at {2}, contains {3} references that may not be assets or are missing",
                                         sceneObject.UUID, sceneObject.Name, sceneObject.AbsolutePosition.ToString(), possible);
                    }
                }

                assetGatherer.GatherAll();

                GC.Collect();

                int errors = assetGatherer.FailedUUIDs.Count;
                m_log.DebugFormat(
                    "[ARCHIVER]: {0} region scene objects to save reference {1} possible assets",
                    sceneObjects.Count, assetUuids.Count - prevAssets + errors);
                if (errors > 0)
                {
                    m_log.DebugFormat("[ARCHIVER]: {0} of these have problems or are not assets and will be ignored", errors);
                }
            }

            if (numObjectsSkippedPermissions > 0)
            {
                m_log.DebugFormat(
                    "[ARCHIVER]: {0} scene objects skipped due to lack of permissions",
                    numObjectsSkippedPermissions);
            }

            // Make sure that we also request terrain texture assets
            RegionSettings regionSettings = scene.RegionInfo.RegionSettings;

            if (regionSettings.TerrainTexture1 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_1)
            {
                assetUuids[regionSettings.TerrainTexture1] = (sbyte)AssetType.Texture;
            }

            if (regionSettings.TerrainTexture2 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_2)
            {
                assetUuids[regionSettings.TerrainTexture2] = (sbyte)AssetType.Texture;
            }

            if (regionSettings.TerrainTexture3 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_3)
            {
                assetUuids[regionSettings.TerrainTexture3] = (sbyte)AssetType.Texture;
            }

            if (regionSettings.TerrainTexture4 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_4)
            {
                assetUuids[regionSettings.TerrainTexture4] = (sbyte)AssetType.Texture;
            }

            if (scene.RegionEnvironment != null)
            {
                scene.RegionEnvironment.GatherAssets(assetUuids);
            }

            List <ILandObject> landObjects = scene.LandChannel.AllParcels();

            foreach (ILandObject lo in landObjects)
            {
                if (lo.LandData != null && lo.LandData.Environment != null)
                {
                    lo.LandData.Environment.GatherAssets(assetUuids);
                }
            }

            Save(scene, sceneObjects, regionDir);
            GC.Collect();
        }
Exemplo n.º 6
0
        private void HandleCheckWearablesCommand(string module, string[] cmd)
        {
            if (cmd.Length != 4)
            {
                MainConsole.Instance.Output("Usage: wearables check <first-name> <last-name>");
                return;
            }

            string firstname = cmd[2];
            string lastname  = cmd[3];

            StringBuilder sb           = new StringBuilder();
            UuidGatherer  uuidGatherer = new UuidGatherer(m_scenes[0].AssetService);

            lock (m_scenes)
            {
                foreach (Scene scene in m_scenes)
                {
                    ScenePresence sp = scene.GetScenePresence(firstname, lastname);
                    if (sp != null && !sp.IsChildAgent)
                    {
                        sb.AppendFormat("Wearables checks for {0}\n\n", sp.Name);

                        AvatarWearable[] wearables = sp.Appearance.Wearables;
                        if (wearables.Length == 0)
                        {
                            MainConsole.Instance.Output("avatar has no wearables");
                            return;
                        }

                        for (int i = 0; i < wearables.Length; i++)
                        {
                            AvatarWearable aw = wearables[i];

                            sb.Append(Enum.GetName(typeof(WearableType), i));
                            sb.Append("\n");
                            if (aw.Count > 0)
                            {
                                for (int j = 0; j < aw.Count; j++)
                                {
                                    WearableItem wi = aw[j];

                                    ConsoleDisplayList cdl = new ConsoleDisplayList();
                                    cdl.Indent = 2;
                                    cdl.AddRow("Item UUID", wi.ItemID);
                                    cdl.AddRow("Assets", "");
                                    sb.Append(cdl.ToString());

                                    uuidGatherer.AddForInspection(wi.AssetID);
                                    uuidGatherer.GatherAll();
                                    string[] assetStrings
                                        = Array.ConvertAll <UUID, string>(uuidGatherer.GatheredUuids.Keys.ToArray(), u => u.ToString());

                                    bool[] existChecks = scene.AssetService.AssetsExist(assetStrings);

                                    ConsoleDisplayTable cdt = new ConsoleDisplayTable();
                                    cdt.Indent = 4;
                                    cdt.AddColumn("Type", 10);
                                    cdt.AddColumn("UUID", ConsoleDisplayUtil.UuidSize);
                                    cdt.AddColumn("Found", 5);

                                    for (int k = 0; k < existChecks.Length; k++)
                                    {
                                        cdt.AddRow(
                                            (AssetType)uuidGatherer.GatheredUuids[new UUID(assetStrings[k])],
                                            assetStrings[k], existChecks[k] ? "yes" : "no");
                                    }

                                    sb.Append(cdt.ToString());
                                    sb.Append("\n");
                                }
                            }
                            else
                            {
                                sb.Append("  Empty\n");
                            }
                        }
                    }
                }
            }

            MainConsole.Instance.Output(sb.ToString());
        }
Exemplo n.º 7
0
        protected void SaveInvItem(InventoryItemBase inventoryItem, string path, Dictionary <string, object> options, IUserAccountService userAccountService)
        {
            if (options.ContainsKey("exclude"))
            {
                if (((List <String>)options["exclude"]).Contains(inventoryItem.Name) ||
                    ((List <String>)options["exclude"]).Contains(inventoryItem.ID.ToString()))
                {
                    if (options.ContainsKey("verbose"))
                    {
                        m_log.InfoFormat(
                            "[INVENTORY ARCHIVER]: Skipping inventory item {0} {1} at {2}",
                            inventoryItem.Name, inventoryItem.ID, path);
                    }

                    CountFiltered++;

                    return;
                }
            }

            // Check For Permissions Filter Flags
            if (!CanUserArchiveObject(m_userInfo.PrincipalID, inventoryItem))
            {
                m_log.InfoFormat(
                    "[INVENTORY ARCHIVER]: Insufficient permissions, skipping inventory item {0} {1} at {2}",
                    inventoryItem.Name, inventoryItem.ID, path);

                // Count Items Excluded
                CountFiltered++;

                return;
            }

            if (options.ContainsKey("verbose"))
            {
                m_log.InfoFormat(
                    "[INVENTORY ARCHIVER]: Saving item {0} {1} (asset UUID {2})",
                    inventoryItem.ID, inventoryItem.Name, inventoryItem.AssetID);
            }

            string filename = path + CreateArchiveItemName(inventoryItem);

            // Record the creator of this item for user record purposes (which might go away soon)
            m_userUuids[inventoryItem.CreatorIdAsUuid] = 1;

            string serialization = UserInventoryItemSerializer.Serialize(inventoryItem, options, userAccountService);

            m_archiveWriter.WriteFile(filename, serialization);

            AssetType itemAssetType = (AssetType)inventoryItem.AssetType;

            // Count inventory items (different to asset count)
            CountItems++;

            // Don't chase down link asset items as they actually point to their target item IDs rather than an asset
            if (SaveAssets && itemAssetType != AssetType.Link && itemAssetType != AssetType.LinkFolder)
            {
                int curErrorCntr = m_assetGatherer.ErrorCount;
                int possible     = m_assetGatherer.possibleNotAssetCount;
                m_assetGatherer.AddForInspection(inventoryItem.AssetID);
                m_assetGatherer.GatherAll();
                curErrorCntr = m_assetGatherer.ErrorCount - curErrorCntr;
                possible     = m_assetGatherer.possibleNotAssetCount - possible;

                if (curErrorCntr > 0 || possible > 0)
                {
                    string spath;
                    int    indx = path.IndexOf("__");
                    if (indx > 0)
                    {
                        spath = path.Substring(0, indx);
                    }
                    else
                    {
                        spath = path;
                    }

                    if (curErrorCntr > 0)
                    {
                        m_log.ErrorFormat("[INVENTORY ARCHIVER Warning]: item {0} '{1}', type {2}, in '{3}', contains {4} references to  missing or damaged assets",
                                          inventoryItem.ID, inventoryItem.Name, itemAssetType.ToString(), spath, curErrorCntr);
                        if (possible > 0)
                        {
                            m_log.WarnFormat("[INVENTORY ARCHIVER Warning]: item also contains {0} references that may be to missing or damaged assets or not a problem", possible);
                        }
                    }
                    else if (possible > 0)
                    {
                        m_log.WarnFormat("[INVENTORY ARCHIVER Warning]: item {0} '{1}', type {2}, in '{3}', contains {4} references that may be to missing or damaged assets or not a problem", inventoryItem.ID, inventoryItem.Name, itemAssetType.ToString(), spath, possible);
                    }
                }
            }
        }
Exemplo n.º 8
0
        private void ArchiveOneRegion(Scene scene, string regionDir, Dictionary <UUID, sbyte> assetUuids)
        {
            m_log.InfoFormat("[ARCHIVER]: Writing region {0}", scene.Name);

            EntityBase[]            entities     = scene.GetEntities();
            List <SceneObjectGroup> sceneObjects = new List <SceneObjectGroup>();

            int numObjectsSkippedPermissions = 0;

            // Filter entities so that we only have scene objects.
            // FIXME: Would be nicer to have this as a proper list in SceneGraph, since lots of methods
            // end up having to do this
            IPermissionsModule permissionsModule = scene.RequestModuleInterface <IPermissionsModule>();

            foreach (EntityBase entity in entities)
            {
                if (entity is SceneObjectGroup)
                {
                    SceneObjectGroup sceneObject = (SceneObjectGroup)entity;

                    if (!sceneObject.IsDeleted && !sceneObject.IsAttachment)
                    {
                        if (!CanUserArchiveObject(scene.RegionInfo.EstateSettings.EstateOwner, sceneObject, FilterContent, permissionsModule))
                        {
                            // The user isn't allowed to copy/transfer this object, so it will not be included in the OAR.
                            ++numObjectsSkippedPermissions;
                        }
                        else
                        {
                            sceneObjects.Add(sceneObject);
                        }
                    }
                }
            }

            if (SaveAssets)
            {
                UuidGatherer assetGatherer = new UuidGatherer(scene.AssetService, assetUuids);
                int          prevAssets    = assetUuids.Count;

                foreach (SceneObjectGroup sceneObject in sceneObjects)
                {
                    assetGatherer.AddForInspection(sceneObject);
                }

                assetGatherer.GatherAll();

                m_log.DebugFormat(
                    "[ARCHIVER]: {0} scene objects to serialize requiring save of {1} assets",
                    sceneObjects.Count, assetUuids.Count - prevAssets);
            }

            if (numObjectsSkippedPermissions > 0)
            {
                m_log.DebugFormat(
                    "[ARCHIVER]: {0} scene objects skipped due to lack of permissions",
                    numObjectsSkippedPermissions);
            }

            // Make sure that we also request terrain texture assets
            RegionSettings regionSettings = scene.RegionInfo.RegionSettings;

            if (regionSettings.TerrainTexture1 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_1)
            {
                assetUuids[regionSettings.TerrainTexture1] = (sbyte)AssetType.Texture;
            }

            if (regionSettings.TerrainTexture2 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_2)
            {
                assetUuids[regionSettings.TerrainTexture2] = (sbyte)AssetType.Texture;
            }

            if (regionSettings.TerrainTexture3 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_3)
            {
                assetUuids[regionSettings.TerrainTexture3] = (sbyte)AssetType.Texture;
            }

            if (regionSettings.TerrainTexture4 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_4)
            {
                assetUuids[regionSettings.TerrainTexture4] = (sbyte)AssetType.Texture;
            }

            Save(scene, sceneObjects, regionDir);
        }
        /// <summary>
        /// Execute the inventory write request
        /// </summary>
        public void Execute(Dictionary <string, object> options, IUserAccountService userAccountService)
        {
            if (options.ContainsKey("noassets") && (bool)options["noassets"])
            {
                SaveAssets = false;
            }

            // Set Permission filter if flag is set
            if (options.ContainsKey("checkPermissions"))
            {
                Object temp;
                if (options.TryGetValue("checkPermissions", out temp))
                {
                    FilterContent = temp.ToString().ToUpper();
                }
            }

            try
            {
                InventoryFolderBase inventoryFolder = null;
                InventoryItemBase   inventoryItem   = null;
                InventoryFolderBase rootFolder      = m_scene.InventoryService.GetRootFolder(m_userInfo.PrincipalID);

                bool saveFolderContentsOnly = false;

                // Eliminate double slashes and any leading / on the path.
                string[] components
                    = m_invPath.Split(
                          new string[] { InventoryFolderImpl.PATH_DELIMITER }, StringSplitOptions.RemoveEmptyEntries);

                int maxComponentIndex = components.Length - 1;

                // If the path terminates with a STAR then later on we want to archive all nodes in the folder but not the
                // folder itself.  This may get more sophisicated later on
                if (maxComponentIndex >= 0 && components[maxComponentIndex] == STAR_WILDCARD)
                {
                    saveFolderContentsOnly = true;
                    maxComponentIndex--;
                }
                else if (maxComponentIndex == -1)
                {
                    // If the user has just specified "/", then don't save the root "My Inventory" folder.  This is
                    // more intuitive then requiring the user to specify "/*" for this.
                    saveFolderContentsOnly = true;
                }

                m_invPath = String.Empty;
                for (int i = 0; i <= maxComponentIndex; i++)
                {
                    m_invPath += components[i] + InventoryFolderImpl.PATH_DELIMITER;
                }

                // Annoyingly Split actually returns the original string if the input string consists only of delimiters
                // Therefore if we still start with a / after the split, then we need the root folder
                if (m_invPath.Length == 0)
                {
                    inventoryFolder = rootFolder;
                }
                else
                {
                    m_invPath = m_invPath.Remove(m_invPath.LastIndexOf(InventoryFolderImpl.PATH_DELIMITER));
                    List <InventoryFolderBase> candidateFolders
                        = InventoryArchiveUtils.FindFoldersByPath(m_scene.InventoryService, rootFolder, m_invPath);
                    if (candidateFolders.Count > 0)
                    {
                        inventoryFolder = candidateFolders[0];
                    }
                }

                // The path may point to an item instead
                if (inventoryFolder == null)
                {
                    inventoryItem = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, rootFolder, m_invPath);
                }

                if (null == inventoryFolder && null == inventoryItem)
                {
                    // We couldn't find the path indicated
                    string    errorMessage = string.Format("Aborted save.  Could not find inventory path {0}", m_invPath);
                    Exception e            = new InventoryArchiverException(errorMessage);
                    m_module.TriggerInventoryArchiveSaved(m_id, false, m_userInfo, m_invPath, m_saveStream, e, 0, 0);
                    throw e;
                }

                m_archiveWriter = new TarArchiveWriter(m_saveStream);

                m_log.InfoFormat("[INVENTORY ARCHIVER]: Adding control file to archive.");

                // Write out control file.  This has to be done first so that subsequent loaders will see this file first
                // XXX: I know this is a weak way of doing it since external non-OAR aware tar executables will not do this
                // not sure how to fix this though, short of going with a completely different file format.
                m_archiveWriter.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, CreateControlFile(options));

                if (inventoryFolder != null)
                {
                    m_log.DebugFormat(
                        "[INVENTORY ARCHIVER]: Found folder {0} {1} at {2}",
                        inventoryFolder.Name,
                        inventoryFolder.ID,
                        m_invPath == String.Empty ? InventoryFolderImpl.PATH_DELIMITER : m_invPath);

                    //recurse through all dirs getting dirs and files
                    SaveInvFolder(inventoryFolder, ArchiveConstants.INVENTORY_PATH, !saveFolderContentsOnly, options, userAccountService);
                }
                else if (inventoryItem != null)
                {
                    m_log.DebugFormat(
                        "[INVENTORY ARCHIVER]: Found item {0} {1} at {2}",
                        inventoryItem.Name, inventoryItem.ID, m_invPath);

                    SaveInvItem(inventoryItem, ArchiveConstants.INVENTORY_PATH, options, userAccountService);
                }

                // Don't put all this profile information into the archive right now.
                //SaveUsers();

                if (SaveAssets)
                {
                    m_assetGatherer.GatherAll();

                    m_log.DebugFormat(
                        "[INVENTORY ARCHIVER]: Saving {0} assets for items", m_assetGatherer.GatheredUuids.Count);

                    AssetsRequest ar
                        = new AssetsRequest(
                              new AssetsArchiver(m_archiveWriter),
                              m_assetGatherer.GatheredUuids, m_scene.AssetService,
                              m_scene.UserAccountService, m_scene.RegionInfo.ScopeID,
                              options, ReceivedAllAssets);

                    WorkManager.RunInThread(o => ar.Execute(), null, string.Format("AssetsRequest ({0})", m_scene.Name));
                }
                else
                {
                    m_log.DebugFormat("[INVENTORY ARCHIVER]: Not saving assets since --noassets was specified");

                    ReceivedAllAssets(new List <UUID>(), new List <UUID>(), false);
                }
            }
            catch (Exception)
            {
                m_saveStream.Close();
                throw;
            }
        }