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