diff --git a/.gitignore b/.gitignore index 9d2d692cf0..b6b5582b0d 100644 --- a/.gitignore +++ b/.gitignore @@ -38,13 +38,21 @@ bin/config-include/CenomeCache.ini bin/config-include/FlotsamCache.ini bin/config-include/GridCommon.ini bin/config-include/StandaloneCommon.ini +bin/OpenSim.Grid.AssetInventoryServer.log +bin/OpenSim.Grid.AssetServer.log +bin/OpenSim.Grid.GridServer.log +bin/OpenSim.Grid.InventoryServer.log +bin/OpenSim.Grid.MessagingServer.log +bin/OpenSim.Grid.UserServer.log +bin/OpenSim.log +bin/crashes/ Examples/*.dll OpenSim.build OpenSim.sln OpenSim.suo Prebuild/Prebuild.build Prebuild/Prebuild.sln -bin/OpenSim.log +TestResult.xml cov/* OpenSim/OpenSim.userprefs OpenSim/OpenSim.usertasks @@ -53,3 +61,4 @@ TAGS Makefile.local bin/.version compile.bat + diff --git a/OpenSim/Framework/Communications/Osp/OspResolver.cs b/OpenSim/Framework/Communications/Osp/OspResolver.cs index 502fee31ad..e98317a3c0 100644 --- a/OpenSim/Framework/Communications/Osp/OspResolver.cs +++ b/OpenSim/Framework/Communications/Osp/OspResolver.cs @@ -153,7 +153,9 @@ namespace OpenSim.Framework.Communications.Osp CachedUserInfo userInfo = commsManager.UserProfileCacheService.GetUserDetails(firstName, lastName); if (userInfo != null) return userInfo.UserProfile.ID; - + + // XXX: Disable temporary user profile creation for now as implementation is incomplete - justincc + /* UserProfileData tempUserProfile = new UserProfileData(); tempUserProfile.FirstName = firstName; tempUserProfile.SurName = lastName; @@ -164,6 +166,9 @@ namespace OpenSim.Framework.Communications.Osp commsManager.UserService.AddTemporaryUserProfile(tempUserProfile); return tempUserProfile.ID; + */ + + return UUID.Zero; } } } diff --git a/OpenSim/Framework/InventoryFolderBase.cs b/OpenSim/Framework/InventoryFolderBase.cs index 0edb2c6103..3eef6f64d6 100644 --- a/OpenSim/Framework/InventoryFolderBase.cs +++ b/OpenSim/Framework/InventoryFolderBase.cs @@ -84,6 +84,14 @@ namespace OpenSim.Framework Owner = owner; } + public InventoryFolderBase(UUID id, string name, UUID owner, UUID parent) + { + ID = id; + Name = name; + Owner = owner; + ParentID = parent; + } + public InventoryFolderBase(UUID id, string name, UUID owner, short type, UUID parent, ushort version) { ID = id; diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs index 38874f9ebd..e6ddb5b739 100644 --- a/OpenSim/Region/Application/OpenSim.cs +++ b/OpenSim/Region/Application/OpenSim.cs @@ -1042,6 +1042,14 @@ namespace OpenSim uint regX = 1000; uint regY = 1000; + IConfig standalone; + if ((standalone = m_config.Source.Configs["StandAlone"]) != null) + { + regX = (uint)standalone.GetInt("default_location_x", (int)regX); + regY = (uint)standalone.GetInt("default_location_y", (int)regY); + } + + if (cmdparams.Length < 3) firstName = MainConsole.Instance.CmdPrompt("First name", "Default"); else firstName = cmdparams[2]; diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs index 49b459a06b..6b0af6d980 100644 --- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs @@ -129,18 +129,18 @@ namespace Flotsam.RegionModules.AssetCache if (name == Name) { m_Enabled = true; - m_log.InfoFormat("[ASSET CACHE]: {0} enabled", this.Name); + m_log.InfoFormat("[FLOTSAM ASSET CACHE]: {0} enabled", this.Name); IConfig assetConfig = source.Configs["AssetCache"]; if (assetConfig == null) { - m_log.Warn("[ASSET CACHE]: AssetCache missing from OpenSim.ini, using defaults."); - m_log.InfoFormat("[ASSET CACHE]: Cache Directory", m_DefaultCacheDirectory); + m_log.Warn("[FLOTSAM ASSET CACHE]: AssetCache missing from OpenSim.ini, using defaults."); + m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Directory", m_DefaultCacheDirectory); return; } m_CacheDirectory = assetConfig.GetString("CacheDirectory", m_DefaultCacheDirectory); - m_log.InfoFormat("[ASSET CACHE]: Cache Directory", m_DefaultCacheDirectory); + m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Directory", m_DefaultCacheDirectory); m_MemoryCacheEnabled = assetConfig.GetBoolean("MemoryCacheEnabled", true); m_MemoryExpiration = TimeSpan.FromHours(assetConfig.GetDouble("MemoryCacheTimeout", m_DefaultMemoryExpiration)); @@ -191,6 +191,8 @@ namespace Flotsam.RegionModules.AssetCache } m_CacheWarnAt = assetConfig.GetInt("CacheWarnAt", 30000); + + } } } @@ -206,7 +208,14 @@ namespace Flotsam.RegionModules.AssetCache public void AddRegion(Scene scene) { if (m_Enabled) + { scene.RegisterModuleInterface(this); + + //scene.AddCommand(this, "flotsamcache", "", "Display a list of console commands for the Flotsam Asset Cache", HandleConsoleCommand); + scene.AddCommand(this, "flotsamcache counts", "flotsamcache counts", "Display the number of cached assets", HandleConsoleCommand); + scene.AddCommand(this, "flotsamcache clearmem", "flotsamcache clearmem", "Remove all assets cached in memory", HandleConsoleCommand); + scene.AddCommand(this, "flotsamcache clearfile", "flotsamcache clearfile", "Remove all assets cached on disk", HandleConsoleCommand); + } } public void RemoveRegion(Scene scene) @@ -368,16 +377,16 @@ namespace Flotsam.RegionModules.AssetCache { m_HitRateFile = (double)m_DiskHits / m_Requests * 100.0; - m_log.InfoFormat("[ASSET CACHE]: Cache Get :: {0} :: {1}", id, asset == null ? "Miss" : "Hit"); - m_log.InfoFormat("[ASSET CACHE]: File Hit Rate {0}% for {1} requests", m_HitRateFile.ToString("0.00"), m_Requests); + m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Get :: {0} :: {1}", id, asset == null ? "Miss" : "Hit"); + m_log.InfoFormat("[FLOTSAM ASSET CACHE]: File Hit Rate {0}% for {1} requests", m_HitRateFile.ToString("0.00"), m_Requests); if (m_MemoryCacheEnabled) { m_HitRateMemory = (double)m_MemoryHits / m_Requests * 100.0; - m_log.InfoFormat("[ASSET CACHE]: Memory Hit Rate {0}% for {1} requests", m_HitRateMemory.ToString("0.00"), m_Requests); + m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Memory Hit Rate {0}% for {1} requests", m_HitRateMemory.ToString("0.00"), m_Requests); } - m_log.InfoFormat("[ASSET CACHE]: {0} unnessesary requests due to requests for assets that are currently downloading.", m_RequestsForInprogress); + m_log.InfoFormat("[FLOTSAM ASSET CACHE]: {0} unnessesary requests due to requests for assets that are currently downloading.", m_RequestsForInprogress); } @@ -387,7 +396,7 @@ namespace Flotsam.RegionModules.AssetCache public void Expire(string id) { if (m_LogLevel >= 2) - m_log.DebugFormat("[ASSET CACHE]: Expiring Asset {0}.", id); + m_log.DebugFormat("[FLOTSAM ASSET CACHE]: Expiring Asset {0}.", id); try { @@ -409,7 +418,7 @@ namespace Flotsam.RegionModules.AssetCache public void Clear() { if (m_LogLevel >= 2) - m_log.Debug("[ASSET CACHE]: Clearing Cache."); + m_log.Debug("[FLOTSAM ASSET CACHE]: Clearing Cache."); foreach (string dir in Directory.GetDirectories(m_CacheDirectory)) { @@ -423,31 +432,44 @@ namespace Flotsam.RegionModules.AssetCache private void CleanupExpiredFiles(object source, ElapsedEventArgs e) { if (m_LogLevel >= 2) - m_log.DebugFormat("[ASSET CACHE]: Checking for expired files older then {0}.", m_FileExpiration.ToString()); + m_log.DebugFormat("[FLOTSAM ASSET CACHE]: Checking for expired files older then {0}.", m_FileExpiration.ToString()); foreach (string dir in Directory.GetDirectories(m_CacheDirectory)) { - foreach (string file in Directory.GetFiles(dir)) - { - if (DateTime.Now - File.GetLastAccessTime(file) > m_FileExpiration) - { - File.Delete(file); - } - } - - int dirSize = Directory.GetFiles(dir).Length; - if (dirSize == 0) - { - Directory.Delete(dir); - } - else if (dirSize >= m_CacheWarnAt) - { - m_log.WarnFormat("[ASSET CACHE]: Cache folder exceeded CacheWarnAt limit {0} {1}. Suggest increasing tiers, tier length, or reducing cache expiration", dir, dirSize); - } - + CleanExpiredFiles(dir); } } + /// + /// Recurses through specified directory checking for expired asset files and deletes them. Also removes empty directories. + /// + /// + private void CleanExpiredFiles(string dir) + { + foreach (string file in Directory.GetFiles(dir)) + { + if (DateTime.Now - File.GetLastAccessTime(file) > m_FileExpiration) + { + File.Delete(file); + } + } + + foreach (string subdir in Directory.GetDirectories(dir)) + { + CleanExpiredFiles(subdir); + } + + int dirSize = Directory.GetFiles(dir).Length + Directory.GetDirectories(dir).Length; + if (dirSize == 0) + { + Directory.Delete(dir); + } + else if (dirSize >= m_CacheWarnAt) + { + m_log.WarnFormat("[FLOTSAM ASSET CACHE]: Cache folder exceeded CacheWarnAt limit {0} {1}. Suggest increasing tiers, tier length, or reducing cache expiration", dir, dirSize); + } + } + private string GetFileName(string id) { // Would it be faster to just hash the darn thing? @@ -489,7 +511,7 @@ namespace Flotsam.RegionModules.AssetCache File.Move(tempname, filename); if (m_LogLevel >= 2) - m_log.DebugFormat("[ASSET CACHE]: Cache Stored :: {0}", asset.ID); + m_log.DebugFormat("[FLOTSAM ASSET CACHE]: Cache Stored :: {0}", asset.ID); } catch (Exception e) { @@ -525,8 +547,88 @@ namespace Flotsam.RegionModules.AssetCache string[] text = e.ToString().Split(new char[] { '\n' }); foreach (string t in text) { - m_log.ErrorFormat("[ASSET CACHE]: {0} ", t); + m_log.ErrorFormat("[FLOTSAM ASSET CACHE]: {0} ", t); } } + + private int GetFileCacheCount(string dir) + { + int count = Directory.GetFiles(dir).Length; + + foreach (string subdir in Directory.GetDirectories(dir)) + { + count += GetFileCacheCount(subdir); + } + + return count; + } + + #region Console Commands + private void HandleConsoleCommand(string module, string[] cmdparams) + { + if (cmdparams.Length == 2) + { + string cmd = cmdparams[1]; + switch (cmd) + { + case "count": + case "counts": + m_log.InfoFormat("[FLOTSAM ASSET CACHE] Memory Cache : {0}", m_MemoryCache.Count); + + int fileCount = GetFileCacheCount(m_CacheDirectory); + m_log.InfoFormat("[FLOTSAM ASSET CACHE] File Cache : {0}", fileCount); + + break; + + case "clearmem": + m_MemoryCache.Clear(); + m_log.InfoFormat("[FLOTSAM ASSET CACHE] Memory Cache Cleared, there are now {0} items in the memory cache", m_MemoryCache.Count); + break; + + case "clearfile": + foreach (string dir in Directory.GetDirectories(m_CacheDirectory)) + { + try + { + Directory.Delete(dir, true); + } + catch (Exception e) + { + LogException(e); + } + } + + foreach (string file in Directory.GetFiles(m_CacheDirectory)) + { + try + { + File.Delete(file); + } + catch (Exception e) + { + LogException(e); + } + } + + break; + + default: + m_log.InfoFormat("[FLOTSAM ASSET CACHE] Unknown command {0}", cmd); + break; + } + } + else if (cmdparams.Length == 1) + { + m_log.InfoFormat("[FLOTSAM ASSET CACHE] flotsamcache counts - Display the number of cached assets"); + m_log.InfoFormat("[FLOTSAM ASSET CACHE] flotsamcache clearmem - Remove all assets cached in memory"); + m_log.InfoFormat("[FLOTSAM ASSET CACHE] flotsamcache clearfile - Remove all assets cached on disk"); + + } + + + } + + #endregion + } } diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs index ff583e5330..2a1c82e715 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs @@ -177,6 +177,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver UUID ospResolvedId = OspResolver.ResolveOspa(item.CreatorId, m_scene.CommsManager); if (UUID.Zero != ospResolvedId) item.CreatorIdAsUuid = ospResolvedId; + else + item.CreatorIdAsUuid = m_userInfo.UserProfile.ID; item.Owner = m_userInfo.UserProfile.ID; @@ -206,7 +208,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// /// Replicate the inventory paths in the archive to the user's inventory as necessary. /// - /// + /// The item archive path to replicate /// Is the path we're dealing with a directory? /// The root folder for the inventory load /// @@ -218,49 +220,51 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// /// The last user inventory folder created or found for the archive path public InventoryFolderBase ReplicateArchivePathToUserInventory( - string fsPath, + string archivePath, bool isDir, InventoryFolderBase rootDestFolder, Dictionary foldersCreated, List nodesLoaded) { - fsPath = fsPath.Substring(ArchiveConstants.INVENTORY_PATH.Length); + archivePath = archivePath.Substring(ArchiveConstants.INVENTORY_PATH.Length); // Remove the file portion if we aren't already dealing with a directory path if (!isDir) - fsPath = fsPath.Remove(fsPath.LastIndexOf("/") + 1); + archivePath = archivePath.Remove(archivePath.LastIndexOf("/") + 1); - string originalFsPath = fsPath; + string originalArchivePath = archivePath; - m_log.DebugFormat("[INVENTORY ARCHIVER]: Loading to folder {0}", fsPath); + m_log.DebugFormat( + "[INVENTORY ARCHIVER]: Loading to folder {0} {1}", rootDestFolder.Name, rootDestFolder.ID); InventoryFolderBase destFolder = null; // XXX: Nasty way of dealing with a path that has no directory component - if (fsPath.Length > 0) + if (archivePath.Length > 0) { - while (null == destFolder && fsPath.Length > 0) + while (null == destFolder && archivePath.Length > 0) { - if (foldersCreated.ContainsKey(fsPath)) + if (foldersCreated.ContainsKey(archivePath)) { - m_log.DebugFormat("[INVENTORY ARCHIVER]: Found previously created fs path {0}", fsPath); - destFolder = foldersCreated[fsPath]; + m_log.DebugFormat( + "[INVENTORY ARCHIVER]: Found previously created folder from archive path {0}", archivePath); + destFolder = foldersCreated[archivePath]; } else { // Don't include the last slash - int penultimateSlashIndex = fsPath.LastIndexOf("/", fsPath.Length - 2); + int penultimateSlashIndex = archivePath.LastIndexOf("/", archivePath.Length - 2); if (penultimateSlashIndex >= 0) { - fsPath = fsPath.Remove(penultimateSlashIndex + 1); + archivePath = archivePath.Remove(penultimateSlashIndex + 1); } else { m_log.DebugFormat( - "[INVENTORY ARCHIVER]: Found no previously created fs path for {0}", - originalFsPath); - fsPath = string.Empty; + "[INVENTORY ARCHIVER]: Found no previously created folder for archive path {0}", + originalArchivePath); + archivePath = string.Empty; destFolder = rootDestFolder; } } @@ -271,14 +275,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver destFolder = rootDestFolder; } - string fsPathSectionToCreate = originalFsPath.Substring(fsPath.Length); + string archivePathSectionToCreate = originalArchivePath.Substring(archivePath.Length); string[] rawDirsToCreate - = fsPathSectionToCreate.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries); + = archivePathSectionToCreate.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries); int i = 0; while (i < rawDirsToCreate.Length) { - m_log.DebugFormat("[INVENTORY ARCHIVER]: Creating folder {0}", rawDirsToCreate[i]); + m_log.DebugFormat("[INVENTORY ARCHIVER]: Loading archived folder {0}", rawDirsToCreate[i]); int identicalNameIdentifierIndex = rawDirsToCreate[i].LastIndexOf( @@ -305,9 +309,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver // foundFolder.Name, foundFolder.ID); // Record that we have now created this folder - fsPath += rawDirsToCreate[i] + "/"; - m_log.DebugFormat("[INVENTORY ARCHIVER]: Recording creation of fs path {0}", fsPath); - foldersCreated[fsPath] = destFolder; + archivePath += rawDirsToCreate[i] + "/"; + m_log.DebugFormat("[INVENTORY ARCHIVER]: Loaded archive path {0}", archivePath); + foldersCreated[archivePath] = destFolder; if (0 == i) nodesLoaded.Add(destFolder); diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs index 2eeb637417..5ebf2faf9a 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs @@ -106,8 +106,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver if (path == PATH_DELIMITER) return startFolder; - InventoryFolderBase foundFolder = null; - string[] components = path.Split(new string[] { PATH_DELIMITER }, 2, StringSplitOptions.None); InventoryCollection contents = inventoryService.GetFolderContent(startFolder.Owner, startFolder.ID); @@ -116,7 +114,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver if (folder.Name == components[0]) { if (components.Length > 1) - return FindFolderByPath(inventoryService, foundFolder, components[1]); + return FindFolderByPath(inventoryService, folder, components[1]); else return folder; } diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs index dee4a5d741..b178772fd7 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs @@ -138,7 +138,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver protected void SaveInvItem(InventoryItemBase inventoryItem, string path) { - string filename = string.Format("{0}{1}_{2}.xml", path, inventoryItem.Name, inventoryItem.ID); + 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; @@ -162,12 +162,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver { if (saveThisFolderItself) { - path += - string.Format( - "{0}{1}{2}/", - inventoryFolder.Name, - ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR, - inventoryFolder.ID); + path += CreateArchiveFolderName(inventoryFolder); // We need to make sure that we record empty folders m_archiveWriter.WriteDir(path); @@ -356,5 +351,63 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver } } } + + /// + /// Create the archive name for a particular folder. + /// + /// + /// These names are prepended with an inventory folder's UUID so that more than one folder can have the + /// same name + /// + /// + /// + public static string CreateArchiveFolderName(InventoryFolderBase folder) + { + return CreateArchiveFolderName(folder.Name, folder.ID); + } + + /// + /// Create the archive name for a particular item. + /// + /// + /// These names are prepended with an inventory item's UUID so that more than one item can have the + /// same name + /// + /// + /// + public static string CreateArchiveItemName(InventoryItemBase item) + { + return CreateArchiveItemName(item.Name, item.ID); + } + + /// + /// Create an archive folder name given its constituent components + /// + /// + /// + /// + public static string CreateArchiveFolderName(string name, UUID id) + { + return string.Format( + "{0}{1}{2}/", + name, + ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR, + id); + } + + /// + /// Create an archive item name given its constituent components + /// + /// + /// + /// + public static string CreateArchiveItemName(string name, UUID id) + { + return string.Format( + "{0}{1}{2}.xml", + name, + ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR, + id); + } } } diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs index d579a81d6d..9c5f8f345f 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs @@ -81,7 +81,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests public void TestSaveIarV0_1() { TestHelper.InMethod(); - log4net.Config.XmlConfigurator.Configure(); + //log4net.Config.XmlConfigurator.Configure(); InventoryArchiverModule archiverModule = new InventoryArchiverModule(true); @@ -153,19 +153,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests //bool gotControlFile = false; bool gotObject1File = false; //bool gotObject2File = false; + string expectedObject1FileName = InventoryArchiveWriteRequest.CreateArchiveItemName(item1); string expectedObject1FilePath = string.Format( - "{0}{1}/{2}_{3}.xml", + "{0}{1}{2}", ArchiveConstants.INVENTORY_PATH, - string.Format( - "Objects{0}{1}", ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR, objsFolder.ID), - item1.Name, - item1Id); - -// string expectedObject2FileName = string.Format( -// "{0}_{1:000}-{2:000}-{3:000}__{4}.xml", -// part2.Name, -// Math.Round(part2.GroupPosition.X), Math.Round(part2.GroupPosition.Y), Math.Round(part2.GroupPosition.Z), -// part2.UUID); + InventoryArchiveWriteRequest.CreateArchiveFolderName(objsFolder), + expectedObject1FileName); string filePath; TarArchiveReader.TarEntryType tarEntryType; @@ -187,7 +180,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests // // if (fileName.StartsWith(part1.Name)) // { - Assert.That(filePath, Is.EqualTo(expectedObject1FilePath)); + Assert.That(expectedObject1FilePath, Is.EqualTo(filePath)); gotObject1File = true; // } // else if (fileName.StartsWith(part2.Name)) @@ -202,19 +195,21 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests Assert.That(gotObject1File, Is.True, "No item1 file in archive"); // Assert.That(gotObject2File, Is.True, "No object2 file in archive"); - // TODO: Test presence of more files and contents of files. + // TODO: Test presence of more files and contents of files. } /// /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where /// an account exists with the creator name. /// + /// + /// This test also does some deeper probing of loading into nested inventory structures [Test] public void TestLoadIarV0_1ExistingUsers() { TestHelper.InMethod(); - log4net.Config.XmlConfigurator.Configure(); + //log4net.Config.XmlConfigurator.Configure(); string userFirstName = "Mr"; string userLastName = "Tiddles"; @@ -264,24 +259,114 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests CachedUserInfo userInfo = scene.CommsManager.UserProfileCacheService.GetUserDetails(userFirstName, userLastName); - InventoryItemBase foundItem + InventoryItemBase foundItem1 = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, userInfo.UserProfile.ID, itemName); - Assert.That(foundItem, Is.Not.Null, "Didn't find loaded item"); + Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1"); Assert.That( - foundItem.CreatorId, Is.EqualTo(item1.CreatorId), + foundItem1.CreatorId, Is.EqualTo(item1.CreatorId), "Loaded item non-uuid creator doesn't match original"); Assert.That( - foundItem.CreatorIdAsUuid, Is.EqualTo(userItemCreatorUuid), + foundItem1.CreatorIdAsUuid, Is.EqualTo(userItemCreatorUuid), "Loaded item uuid creator doesn't match original"); - Assert.That(foundItem.Owner, Is.EqualTo(userUuid), + Assert.That(foundItem1.Owner, Is.EqualTo(userUuid), "Loaded item owner doesn't match inventory reciever"); + + // Now try loading to a root child folder + UserInventoryTestUtils.CreateInventoryFolder(scene.InventoryService, userInfo.UserProfile.ID, "xA"); + archiveReadStream = new MemoryStream(archiveReadStream.ToArray()); + archiverModule.DearchiveInventory(userFirstName, userLastName, "xA", archiveReadStream); + + InventoryItemBase foundItem2 + = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, userInfo.UserProfile.ID, "xA/" + itemName); + Assert.That(foundItem2, Is.Not.Null, "Didn't find loaded item 2"); + + // Now try loading to a more deeply nested folder + UserInventoryTestUtils.CreateInventoryFolder(scene.InventoryService, userInfo.UserProfile.ID, "xB/xC"); + archiveReadStream = new MemoryStream(archiveReadStream.ToArray()); + archiverModule.DearchiveInventory(userFirstName, userLastName, "xB/xC", archiveReadStream); + + InventoryItemBase foundItem3 + = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, userInfo.UserProfile.ID, "xB/xC/" + itemName); + Assert.That(foundItem3, Is.Not.Null, "Didn't find loaded item 3"); } + /// + /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where + /// embedded creators do not exist in the system + /// + /// + /// This may possibly one day get overtaken by the as yet incomplete temporary profiles feature + /// (as tested in the a later commented out test) + [Test] + public void TestLoadIarV0_1AbsentUsers() + { + TestHelper.InMethod(); + + log4net.Config.XmlConfigurator.Configure(); + + string userFirstName = "Charlie"; + string userLastName = "Chan"; + UUID userUuid = UUID.Parse("00000000-0000-0000-0000-000000000999"); + string userItemCreatorFirstName = "Bat"; + string userItemCreatorLastName = "Man"; + //UUID userItemCreatorUuid = UUID.Parse("00000000-0000-0000-0000-000000008888"); + + string itemName = "b.lsl"; + string archiveItemName + = string.Format("{0}{1}{2}", itemName, "_", UUID.Random()); + + MemoryStream archiveWriteStream = new MemoryStream(); + TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream); + + InventoryItemBase item1 = new InventoryItemBase(); + item1.Name = itemName; + item1.AssetID = UUID.Random(); + item1.GroupID = UUID.Random(); + item1.CreatorId = OspResolver.MakeOspa(userItemCreatorFirstName, userItemCreatorLastName); + //item1.CreatorId = userUuid.ToString(); + //item1.CreatorId = "00000000-0000-0000-0000-000000000444"; + item1.Owner = UUID.Zero; + + string item1FileName + = string.Format("{0}{1}", ArchiveConstants.INVENTORY_PATH, archiveItemName); + tar.WriteFile(item1FileName, UserInventoryItemSerializer.Serialize(item1)); + tar.Close(); + + MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray()); + SerialiserModule serialiserModule = new SerialiserModule(); + InventoryArchiverModule archiverModule = new InventoryArchiverModule(true); + + // Annoyingly, we have to set up a scene even though inventory loading has nothing to do with a scene + Scene scene = SceneSetupHelpers.SetupScene("inventory"); + IUserAdminService userAdminService = scene.CommsManager.UserAdminService; + + SceneSetupHelpers.SetupSceneModules(scene, serialiserModule, archiverModule); + userAdminService.AddUser( + userFirstName, userLastName, "meowfood", String.Empty, 1000, 1000, userUuid); + + archiverModule.DearchiveInventory(userFirstName, userLastName, "/", archiveReadStream); + + CachedUserInfo userInfo + = scene.CommsManager.UserProfileCacheService.GetUserDetails(userFirstName, userLastName); + + InventoryItemBase foundItem1 + = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, userInfo.UserProfile.ID, itemName); + + Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1"); +// Assert.That( +// foundItem1.CreatorId, Is.EqualTo(userUuid), +// "Loaded item non-uuid creator doesn't match that of the loading user"); + Assert.That( + foundItem1.CreatorIdAsUuid, Is.EqualTo(userUuid), + "Loaded item uuid creator doesn't match that of the loading user"); + } + /// /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where /// no account exists with the creator name /// + /// Disabled since temporary profiles have not yet been implemented. //[Test] public void TestLoadIarV0_1TempProfiles() { @@ -364,7 +449,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests { TestHelper.InMethod(); - log4net.Config.XmlConfigurator.Configure(); + //log4net.Config.XmlConfigurator.Configure(); Scene scene = SceneSetupHelpers.SetupScene("inventory"); CommunicationsManager commsManager = scene.CommsManager; @@ -385,16 +470,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests string folder2Name = "b"; string itemName = "c.lsl"; - string folder1ArchiveName - = string.Format( - "{0}{1}{2}", folder1Name, ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR, UUID.Random()); - string folder2ArchiveName - = string.Format( - "{0}{1}{2}", folder2Name, ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR, UUID.Random()); + string folder1ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder1Name, UUID.Random()); + string folder2ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2Name, UUID.Random()); + string itemArchiveName = InventoryArchiveWriteRequest.CreateArchiveItemName(itemName, UUID.Random()); + string itemArchivePath = string.Format( - "{0}{1}/{2}/{3}", - ArchiveConstants.INVENTORY_PATH, folder1ArchiveName, folder2ArchiveName, itemName); + "{0}{1}{2}{3}", + ArchiveConstants.INVENTORY_PATH, folder1ArchiveName, folder2ArchiveName, itemArchiveName); //Console.WriteLine("userInfo.RootFolder 2: {0}", userInfo.RootFolder); diff --git a/OpenSim/Region/CoreModules/World/Land/RegionCombinerModule.cs b/OpenSim/Region/CoreModules/World/Land/RegionCombinerModule.cs index 9da869cb92..f513d68718 100644 --- a/OpenSim/Region/CoreModules/World/Land/RegionCombinerModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/RegionCombinerModule.cs @@ -588,10 +588,9 @@ namespace OpenSim.Region.CoreModules.World.Land RegionConnections connectiondata, ScenePresence rootPresence) { RegionData[] rdata = connectiondata.ConnectedRegions.ToArray(); - List clients = new List(); + //List clients = new List(); Dictionary updates = new Dictionary(); - // Root Region entry RegionCourseLocationStruct rootupdatedata = new RegionCourseLocationStruct(); rootupdatedata.Locations = new List(); diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index d43a7e22e6..ecf0d807ae 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1297,6 +1297,7 @@ namespace OpenSim.Region.Framework.Scenes m_log.Warn("[TERRAIN]: Scene.cs: LoadWorldMap() - Failed with exception " + e.ToString() + " Regenerating"); // Non standard region size. If there's an old terrain in the database, it might read past the buffer + #pragma warning disable 0162 if ((int)Constants.RegionSize != 256) { Heightmap = new TerrainChannel(); diff --git a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs index fea288e387..94223d8212 100644 --- a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs +++ b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs @@ -3488,7 +3488,7 @@ namespace OpenSim.Region.Physics.OdePlugin { if (geom == localGround) { - localHeightfield = TerrainHeightFieldHeights[geom]; + //localHeightfield = TerrainHeightFieldHeights[geom]; proceed = true; } else @@ -3510,7 +3510,7 @@ namespace OpenSim.Region.Physics.OdePlugin // memory corruption if (TerrainHeightFieldHeights.ContainsKey(g)) { - float[] removingHeightField = TerrainHeightFieldHeights[g]; + //float[] removingHeightField = TerrainHeightFieldHeights[g]; TerrainHeightFieldHeights.Remove(g); if (RegionTerrain.ContainsKey(g)) @@ -3519,27 +3519,17 @@ namespace OpenSim.Region.Physics.OdePlugin } d.GeomDestroy(g); - removingHeightField = new float[0]; - - - - } - + //removingHeightField = new float[0]; + } } - } else { m_log.Warn("[PHYSICS]: Couldn't proceed with UnCombine. Region has inconsistant data."); - } - - } - + } } - } - - + } public override void SetWaterLevel(float baseheight) { diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index f261c16d32..02befda49c 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -9477,8 +9477,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return; } - System.Text.ASCIIEncoding enc = - new System.Text.ASCIIEncoding(); + System.Text.UTF8Encoding enc = + new System.Text.UTF8Encoding(); string data = enc.GetString(a.Data); //m_log.Debug(data); NotecardCache.Cache(id, data); @@ -9524,29 +9524,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (NotecardCache.IsCached(assetID)) { - AsyncCommands. - DataserverPlugin.DataserverReply(assetID.ToString(), - NotecardCache.GetLine(assetID, line, m_notecardLineReadCharsMax)); + AsyncCommands.DataserverPlugin.DataserverReply(assetID.ToString(), + NotecardCache.GetLine(assetID, line, m_notecardLineReadCharsMax)); ConditionalScriptSleep(100); return tid.ToString(); } WithNotecard(assetID, delegate (UUID id, AssetBase a) - { - if (a == null || a.Type != 7) - { - ShoutError("Notecard '" + name + "' could not be found."); - return; - } + { + if (a == null || a.Type != 7) + { + ShoutError("Notecard '" + name + "' could not be found."); + return; + } - System.Text.ASCIIEncoding enc = - new System.Text.ASCIIEncoding(); - string data = enc.GetString(a.Data); - //m_log.Debug(data); - NotecardCache.Cache(id, data); - AsyncCommands.DataserverPlugin.DataserverReply(id.ToString(), - NotecardCache.GetLine(id, line, m_notecardLineReadCharsMax)); - }); + System.Text.UTF8Encoding enc = + new System.Text.UTF8Encoding(); + string data = enc.GetString(a.Data); + //m_log.Debug(data); + NotecardCache.Cache(id, data); + AsyncCommands.DataserverPlugin.DataserverReply(id.ToString(), + NotecardCache.GetLine(id, line, m_notecardLineReadCharsMax)); + }); ConditionalScriptSleep(100); return tid.ToString(); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index bca019b72d..726b37a077 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -1457,7 +1457,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api notecardData = "Linden text version 2\n{\nLLEmbeddedItems version 1\n{\ncount 0\n}\nText length " + textLength.ToString() + "\n" + notecardData + "}\n"; - asset.Data = Encoding.ASCII.GetBytes(notecardData); + asset.Data = Encoding.UTF8.GetBytes(notecardData); World.AssetService.Store(asset); // Create Task Entry @@ -1522,7 +1522,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api AssetBase a = World.AssetService.Get(assetID.ToString()); if (a != null) { - System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(); + System.Text.UTF8Encoding enc = new System.Text.UTF8Encoding(); string data = enc.GetString(a.Data); NotecardCache.Cache(assetID, data); } @@ -1575,7 +1575,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api AssetBase a = World.AssetService.Get(assetID.ToString()); if (a != null) { - System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(); + System.Text.UTF8Encoding enc = new System.Text.UTF8Encoding(); string data = enc.GetString(a.Data); NotecardCache.Cache(assetID, data); } @@ -1632,7 +1632,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api AssetBase a = World.AssetService.Get(assetID.ToString()); if (a != null) { - System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(); + System.Text.UTF8Encoding enc = new System.Text.UTF8Encoding(); string data = enc.GetString(a.Data); NotecardCache.Cache(assetID, data); } diff --git a/OpenSim/Tests/Common/Setup/UserInventoryTestUtils.cs b/OpenSim/Tests/Common/Setup/UserInventoryTestUtils.cs new file mode 100644 index 0000000000..352807213f --- /dev/null +++ b/OpenSim/Tests/Common/Setup/UserInventoryTestUtils.cs @@ -0,0 +1,97 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Services.Interfaces; + +namespace OpenSim.Tests.Common +{ + /// + /// Utility functions for carrying out user inventory related tests. + /// + public static class UserInventoryTestUtils + { + public static readonly string PATH_DELIMITER = "/"; + + /// + /// Create inventory folders starting from the user's root folder. + /// + /// + /// Ignores any existing folders with the same name + /// + /// + /// + /// + /// The folders to create. Multiple folders can be specified on a path delimited by the PATH_DELIMITER + /// + /// + /// The folder created. If the path contains multiple folders then the last one created is returned. + /// Will return null if the root folder could not be found. + /// + public static InventoryFolderBase CreateInventoryFolder( + IInventoryService inventoryService, UUID userId, string path) + { + InventoryFolderBase rootFolder = inventoryService.GetRootFolder(userId); + + if (null == rootFolder) + return null; + + return CreateInventoryFolder(inventoryService, rootFolder, path); + } + + /// + /// Create inventory folders starting from a given parent folder + /// + /// + /// Ignores any existing folders with the same name + /// + /// + /// + /// + /// The folders to create. Multiple folders can be specified on a path delimited by the PATH_DELIMITER + /// + /// + /// The folder created. If the path contains multiple folders then the last one created is returned. + /// + public static InventoryFolderBase CreateInventoryFolder( + IInventoryService inventoryService, InventoryFolderBase parentFolder, string path) + { + string[] components = path.Split(new string[] { PATH_DELIMITER }, 2, StringSplitOptions.None); + + InventoryFolderBase newFolder + = new InventoryFolderBase(UUID.Random(), components[0], parentFolder.Owner, parentFolder.ID); + inventoryService.AddFolder(newFolder); + + if (components.Length > 1) + return CreateInventoryFolder(inventoryService, newFolder, components[1]); + else + return newFolder; + } + } +} \ No newline at end of file diff --git a/OpenSim/Tests/Common/Setup/UserProfileTestUtils.cs b/OpenSim/Tests/Common/Setup/UserProfileTestUtils.cs index f146a15df9..4ad9926734 100644 --- a/OpenSim/Tests/Common/Setup/UserProfileTestUtils.cs +++ b/OpenSim/Tests/Common/Setup/UserProfileTestUtils.cs @@ -35,7 +35,7 @@ namespace OpenSim.Tests.Common.Setup /// /// Utility functions for carrying out user profile related tests. /// - public class UserProfileTestUtils + public static class UserProfileTestUtils { /// /// Create a test user with a standard inventory