Merge branch 'master' of ssh://MyConnection/var/git/opensim

remotes/origin/0.6.7-post-fixes
Teravus Ovares (Dan Olivares) 2009-09-09 16:20:46 -04:00
commit df9f80aabd
16 changed files with 492 additions and 136 deletions

11
.gitignore vendored
View File

@ -38,13 +38,21 @@ bin/config-include/CenomeCache.ini
bin/config-include/FlotsamCache.ini bin/config-include/FlotsamCache.ini
bin/config-include/GridCommon.ini bin/config-include/GridCommon.ini
bin/config-include/StandaloneCommon.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 Examples/*.dll
OpenSim.build OpenSim.build
OpenSim.sln OpenSim.sln
OpenSim.suo OpenSim.suo
Prebuild/Prebuild.build Prebuild/Prebuild.build
Prebuild/Prebuild.sln Prebuild/Prebuild.sln
bin/OpenSim.log TestResult.xml
cov/* cov/*
OpenSim/OpenSim.userprefs OpenSim/OpenSim.userprefs
OpenSim/OpenSim.usertasks OpenSim/OpenSim.usertasks
@ -53,3 +61,4 @@ TAGS
Makefile.local Makefile.local
bin/.version bin/.version
compile.bat compile.bat

View File

@ -154,6 +154,8 @@ namespace OpenSim.Framework.Communications.Osp
if (userInfo != null) if (userInfo != null)
return userInfo.UserProfile.ID; return userInfo.UserProfile.ID;
// XXX: Disable temporary user profile creation for now as implementation is incomplete - justincc
/*
UserProfileData tempUserProfile = new UserProfileData(); UserProfileData tempUserProfile = new UserProfileData();
tempUserProfile.FirstName = firstName; tempUserProfile.FirstName = firstName;
tempUserProfile.SurName = lastName; tempUserProfile.SurName = lastName;
@ -164,6 +166,9 @@ namespace OpenSim.Framework.Communications.Osp
commsManager.UserService.AddTemporaryUserProfile(tempUserProfile); commsManager.UserService.AddTemporaryUserProfile(tempUserProfile);
return tempUserProfile.ID; return tempUserProfile.ID;
*/
return UUID.Zero;
} }
} }
} }

View File

@ -84,6 +84,14 @@ namespace OpenSim.Framework
Owner = owner; 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) public InventoryFolderBase(UUID id, string name, UUID owner, short type, UUID parent, ushort version)
{ {
ID = id; ID = id;

View File

@ -1042,6 +1042,14 @@ namespace OpenSim
uint regX = 1000; uint regX = 1000;
uint regY = 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) if (cmdparams.Length < 3)
firstName = MainConsole.Instance.CmdPrompt("First name", "Default"); firstName = MainConsole.Instance.CmdPrompt("First name", "Default");
else firstName = cmdparams[2]; else firstName = cmdparams[2];

View File

@ -129,18 +129,18 @@ namespace Flotsam.RegionModules.AssetCache
if (name == Name) if (name == Name)
{ {
m_Enabled = true; 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"]; IConfig assetConfig = source.Configs["AssetCache"];
if (assetConfig == null) if (assetConfig == null)
{ {
m_log.Warn("[ASSET CACHE]: AssetCache missing from OpenSim.ini, using defaults."); m_log.Warn("[FLOTSAM ASSET CACHE]: AssetCache missing from OpenSim.ini, using defaults.");
m_log.InfoFormat("[ASSET CACHE]: Cache Directory", m_DefaultCacheDirectory); m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Directory", m_DefaultCacheDirectory);
return; return;
} }
m_CacheDirectory = assetConfig.GetString("CacheDirectory", m_DefaultCacheDirectory); 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_MemoryCacheEnabled = assetConfig.GetBoolean("MemoryCacheEnabled", true);
m_MemoryExpiration = TimeSpan.FromHours(assetConfig.GetDouble("MemoryCacheTimeout", m_DefaultMemoryExpiration)); m_MemoryExpiration = TimeSpan.FromHours(assetConfig.GetDouble("MemoryCacheTimeout", m_DefaultMemoryExpiration));
@ -191,6 +191,8 @@ namespace Flotsam.RegionModules.AssetCache
} }
m_CacheWarnAt = assetConfig.GetInt("CacheWarnAt", 30000); m_CacheWarnAt = assetConfig.GetInt("CacheWarnAt", 30000);
} }
} }
} }
@ -206,7 +208,14 @@ namespace Flotsam.RegionModules.AssetCache
public void AddRegion(Scene scene) public void AddRegion(Scene scene)
{ {
if (m_Enabled) if (m_Enabled)
{
scene.RegisterModuleInterface<IImprovedAssetCache>(this); scene.RegisterModuleInterface<IImprovedAssetCache>(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) public void RemoveRegion(Scene scene)
@ -368,16 +377,16 @@ namespace Flotsam.RegionModules.AssetCache
{ {
m_HitRateFile = (double)m_DiskHits / m_Requests * 100.0; 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("[FLOTSAM 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]: File Hit Rate {0}% for {1} requests", m_HitRateFile.ToString("0.00"), m_Requests);
if (m_MemoryCacheEnabled) if (m_MemoryCacheEnabled)
{ {
m_HitRateMemory = (double)m_MemoryHits / m_Requests * 100.0; 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) public void Expire(string id)
{ {
if (m_LogLevel >= 2) if (m_LogLevel >= 2)
m_log.DebugFormat("[ASSET CACHE]: Expiring Asset {0}.", id); m_log.DebugFormat("[FLOTSAM ASSET CACHE]: Expiring Asset {0}.", id);
try try
{ {
@ -409,7 +418,7 @@ namespace Flotsam.RegionModules.AssetCache
public void Clear() public void Clear()
{ {
if (m_LogLevel >= 2) 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)) foreach (string dir in Directory.GetDirectories(m_CacheDirectory))
{ {
@ -423,28 +432,41 @@ namespace Flotsam.RegionModules.AssetCache
private void CleanupExpiredFiles(object source, ElapsedEventArgs e) private void CleanupExpiredFiles(object source, ElapsedEventArgs e)
{ {
if (m_LogLevel >= 2) 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 dir in Directory.GetDirectories(m_CacheDirectory))
{ {
foreach (string file in Directory.GetFiles(dir)) CleanExpiredFiles(dir);
{ }
if (DateTime.Now - File.GetLastAccessTime(file) > m_FileExpiration) }
{
File.Delete(file);
}
}
int dirSize = Directory.GetFiles(dir).Length; /// <summary>
if (dirSize == 0) /// Recurses through specified directory checking for expired asset files and deletes them. Also removes empty directories.
/// </summary>
/// <param name="dir"></param>
private void CleanExpiredFiles(string dir)
{
foreach (string file in Directory.GetFiles(dir))
{
if (DateTime.Now - File.GetLastAccessTime(file) > m_FileExpiration)
{ {
Directory.Delete(dir); File.Delete(file);
}
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);
} }
}
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);
} }
} }
@ -489,7 +511,7 @@ namespace Flotsam.RegionModules.AssetCache
File.Move(tempname, filename); File.Move(tempname, filename);
if (m_LogLevel >= 2) 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) catch (Exception e)
{ {
@ -525,8 +547,88 @@ namespace Flotsam.RegionModules.AssetCache
string[] text = e.ToString().Split(new char[] { '\n' }); string[] text = e.ToString().Split(new char[] { '\n' });
foreach (string t in text) 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
} }
} }

View File

@ -177,6 +177,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
UUID ospResolvedId = OspResolver.ResolveOspa(item.CreatorId, m_scene.CommsManager); UUID ospResolvedId = OspResolver.ResolveOspa(item.CreatorId, m_scene.CommsManager);
if (UUID.Zero != ospResolvedId) if (UUID.Zero != ospResolvedId)
item.CreatorIdAsUuid = ospResolvedId; item.CreatorIdAsUuid = ospResolvedId;
else
item.CreatorIdAsUuid = m_userInfo.UserProfile.ID;
item.Owner = m_userInfo.UserProfile.ID; item.Owner = m_userInfo.UserProfile.ID;
@ -206,7 +208,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
/// <summary> /// <summary>
/// Replicate the inventory paths in the archive to the user's inventory as necessary. /// Replicate the inventory paths in the archive to the user's inventory as necessary.
/// </summary> /// </summary>
/// <param name="fsPath"></param> /// <param name="archivePath">The item archive path to replicate</param>
/// <param name="isDir">Is the path we're dealing with a directory?</param> /// <param name="isDir">Is the path we're dealing with a directory?</param>
/// <param name="rootDestinationFolder">The root folder for the inventory load</param> /// <param name="rootDestinationFolder">The root folder for the inventory load</param>
/// <param name="foldersCreated"> /// <param name="foldersCreated">
@ -218,49 +220,51 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
/// </param> /// </param>
/// <returns>The last user inventory folder created or found for the archive path</returns> /// <returns>The last user inventory folder created or found for the archive path</returns>
public InventoryFolderBase ReplicateArchivePathToUserInventory( public InventoryFolderBase ReplicateArchivePathToUserInventory(
string fsPath, string archivePath,
bool isDir, bool isDir,
InventoryFolderBase rootDestFolder, InventoryFolderBase rootDestFolder,
Dictionary <string, InventoryFolderBase> foldersCreated, Dictionary <string, InventoryFolderBase> foldersCreated,
List<InventoryNodeBase> nodesLoaded) List<InventoryNodeBase> 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 // Remove the file portion if we aren't already dealing with a directory path
if (!isDir) 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; InventoryFolderBase destFolder = null;
// XXX: Nasty way of dealing with a path that has no directory component // 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); m_log.DebugFormat(
destFolder = foldersCreated[fsPath]; "[INVENTORY ARCHIVER]: Found previously created folder from archive path {0}", archivePath);
destFolder = foldersCreated[archivePath];
} }
else else
{ {
// Don't include the last slash // Don't include the last slash
int penultimateSlashIndex = fsPath.LastIndexOf("/", fsPath.Length - 2); int penultimateSlashIndex = archivePath.LastIndexOf("/", archivePath.Length - 2);
if (penultimateSlashIndex >= 0) if (penultimateSlashIndex >= 0)
{ {
fsPath = fsPath.Remove(penultimateSlashIndex + 1); archivePath = archivePath.Remove(penultimateSlashIndex + 1);
} }
else else
{ {
m_log.DebugFormat( m_log.DebugFormat(
"[INVENTORY ARCHIVER]: Found no previously created fs path for {0}", "[INVENTORY ARCHIVER]: Found no previously created folder for archive path {0}",
originalFsPath); originalArchivePath);
fsPath = string.Empty; archivePath = string.Empty;
destFolder = rootDestFolder; destFolder = rootDestFolder;
} }
} }
@ -271,14 +275,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
destFolder = rootDestFolder; destFolder = rootDestFolder;
} }
string fsPathSectionToCreate = originalFsPath.Substring(fsPath.Length); string archivePathSectionToCreate = originalArchivePath.Substring(archivePath.Length);
string[] rawDirsToCreate string[] rawDirsToCreate
= fsPathSectionToCreate.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries); = archivePathSectionToCreate.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
int i = 0; int i = 0;
while (i < rawDirsToCreate.Length) 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 int identicalNameIdentifierIndex
= rawDirsToCreate[i].LastIndexOf( = rawDirsToCreate[i].LastIndexOf(
@ -305,9 +309,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
// foundFolder.Name, foundFolder.ID); // foundFolder.Name, foundFolder.ID);
// Record that we have now created this folder // Record that we have now created this folder
fsPath += rawDirsToCreate[i] + "/"; archivePath += rawDirsToCreate[i] + "/";
m_log.DebugFormat("[INVENTORY ARCHIVER]: Recording creation of fs path {0}", fsPath); m_log.DebugFormat("[INVENTORY ARCHIVER]: Loaded archive path {0}", archivePath);
foldersCreated[fsPath] = destFolder; foldersCreated[archivePath] = destFolder;
if (0 == i) if (0 == i)
nodesLoaded.Add(destFolder); nodesLoaded.Add(destFolder);

View File

@ -106,8 +106,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
if (path == PATH_DELIMITER) if (path == PATH_DELIMITER)
return startFolder; return startFolder;
InventoryFolderBase foundFolder = null;
string[] components = path.Split(new string[] { PATH_DELIMITER }, 2, StringSplitOptions.None); string[] components = path.Split(new string[] { PATH_DELIMITER }, 2, StringSplitOptions.None);
InventoryCollection contents = inventoryService.GetFolderContent(startFolder.Owner, startFolder.ID); 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 (folder.Name == components[0])
{ {
if (components.Length > 1) if (components.Length > 1)
return FindFolderByPath(inventoryService, foundFolder, components[1]); return FindFolderByPath(inventoryService, folder, components[1]);
else else
return folder; return folder;
} }

View File

@ -138,7 +138,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
protected void SaveInvItem(InventoryItemBase inventoryItem, string path) 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) // Record the creator of this item for user record purposes (which might go away soon)
m_userUuids[inventoryItem.CreatorIdAsUuid] = 1; m_userUuids[inventoryItem.CreatorIdAsUuid] = 1;
@ -162,12 +162,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
{ {
if (saveThisFolderItself) if (saveThisFolderItself)
{ {
path += path += CreateArchiveFolderName(inventoryFolder);
string.Format(
"{0}{1}{2}/",
inventoryFolder.Name,
ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR,
inventoryFolder.ID);
// We need to make sure that we record empty folders // We need to make sure that we record empty folders
m_archiveWriter.WriteDir(path); m_archiveWriter.WriteDir(path);
@ -356,5 +351,63 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
} }
} }
} }
/// <summary>
/// Create the archive name for a particular folder.
/// </summary>
///
/// These names are prepended with an inventory folder's UUID so that more than one folder can have the
/// same name
///
/// <param name="folder"></param>
/// <returns></returns>
public static string CreateArchiveFolderName(InventoryFolderBase folder)
{
return CreateArchiveFolderName(folder.Name, folder.ID);
}
/// <summary>
/// Create the archive name for a particular item.
/// </summary>
///
/// These names are prepended with an inventory item's UUID so that more than one item can have the
/// same name
///
/// <param name="item"></param>
/// <returns></returns>
public static string CreateArchiveItemName(InventoryItemBase item)
{
return CreateArchiveItemName(item.Name, item.ID);
}
/// <summary>
/// Create an archive folder name given its constituent components
/// </summary>
/// <param name="name"></param>
/// <param name="id"></param>
/// <returns></returns>
public static string CreateArchiveFolderName(string name, UUID id)
{
return string.Format(
"{0}{1}{2}/",
name,
ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR,
id);
}
/// <summary>
/// Create an archive item name given its constituent components
/// </summary>
/// <param name="name"></param>
/// <param name="id"></param>
/// <returns></returns>
public static string CreateArchiveItemName(string name, UUID id)
{
return string.Format(
"{0}{1}{2}.xml",
name,
ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR,
id);
}
} }
} }

View File

@ -81,7 +81,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
public void TestSaveIarV0_1() public void TestSaveIarV0_1()
{ {
TestHelper.InMethod(); TestHelper.InMethod();
log4net.Config.XmlConfigurator.Configure(); //log4net.Config.XmlConfigurator.Configure();
InventoryArchiverModule archiverModule = new InventoryArchiverModule(true); InventoryArchiverModule archiverModule = new InventoryArchiverModule(true);
@ -153,19 +153,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
//bool gotControlFile = false; //bool gotControlFile = false;
bool gotObject1File = false; bool gotObject1File = false;
//bool gotObject2File = false; //bool gotObject2File = false;
string expectedObject1FileName = InventoryArchiveWriteRequest.CreateArchiveItemName(item1);
string expectedObject1FilePath = string.Format( string expectedObject1FilePath = string.Format(
"{0}{1}/{2}_{3}.xml", "{0}{1}{2}",
ArchiveConstants.INVENTORY_PATH, ArchiveConstants.INVENTORY_PATH,
string.Format( InventoryArchiveWriteRequest.CreateArchiveFolderName(objsFolder),
"Objects{0}{1}", ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR, objsFolder.ID), expectedObject1FileName);
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);
string filePath; string filePath;
TarArchiveReader.TarEntryType tarEntryType; TarArchiveReader.TarEntryType tarEntryType;
@ -187,7 +180,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
// //
// if (fileName.StartsWith(part1.Name)) // if (fileName.StartsWith(part1.Name))
// { // {
Assert.That(filePath, Is.EqualTo(expectedObject1FilePath)); Assert.That(expectedObject1FilePath, Is.EqualTo(filePath));
gotObject1File = true; gotObject1File = true;
// } // }
// else if (fileName.StartsWith(part2.Name)) // else if (fileName.StartsWith(part2.Name))
@ -209,12 +202,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
/// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where /// 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. /// an account exists with the creator name.
/// </summary> /// </summary>
///
/// This test also does some deeper probing of loading into nested inventory structures
[Test] [Test]
public void TestLoadIarV0_1ExistingUsers() public void TestLoadIarV0_1ExistingUsers()
{ {
TestHelper.InMethod(); TestHelper.InMethod();
log4net.Config.XmlConfigurator.Configure(); //log4net.Config.XmlConfigurator.Configure();
string userFirstName = "Mr"; string userFirstName = "Mr";
string userLastName = "Tiddles"; string userLastName = "Tiddles";
@ -264,24 +259,114 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
CachedUserInfo userInfo CachedUserInfo userInfo
= scene.CommsManager.UserProfileCacheService.GetUserDetails(userFirstName, userLastName); = scene.CommsManager.UserProfileCacheService.GetUserDetails(userFirstName, userLastName);
InventoryItemBase foundItem InventoryItemBase foundItem1
= InventoryArchiveUtils.FindItemByPath(scene.InventoryService, userInfo.UserProfile.ID, itemName); = 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( Assert.That(
foundItem.CreatorId, Is.EqualTo(item1.CreatorId), foundItem1.CreatorId, Is.EqualTo(item1.CreatorId),
"Loaded item non-uuid creator doesn't match original"); "Loaded item non-uuid creator doesn't match original");
Assert.That( Assert.That(
foundItem.CreatorIdAsUuid, Is.EqualTo(userItemCreatorUuid), foundItem1.CreatorIdAsUuid, Is.EqualTo(userItemCreatorUuid),
"Loaded item uuid creator doesn't match original"); "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"); "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");
}
/// <summary>
/// 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
/// </summary>
///
/// 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");
} }
/// <summary> /// <summary>
/// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where /// 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 /// no account exists with the creator name
/// </summary> /// </summary>
/// Disabled since temporary profiles have not yet been implemented.
//[Test] //[Test]
public void TestLoadIarV0_1TempProfiles() public void TestLoadIarV0_1TempProfiles()
{ {
@ -364,7 +449,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
{ {
TestHelper.InMethod(); TestHelper.InMethod();
log4net.Config.XmlConfigurator.Configure(); //log4net.Config.XmlConfigurator.Configure();
Scene scene = SceneSetupHelpers.SetupScene("inventory"); Scene scene = SceneSetupHelpers.SetupScene("inventory");
CommunicationsManager commsManager = scene.CommsManager; CommunicationsManager commsManager = scene.CommsManager;
@ -385,16 +470,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
string folder2Name = "b"; string folder2Name = "b";
string itemName = "c.lsl"; string itemName = "c.lsl";
string folder1ArchiveName string folder1ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder1Name, UUID.Random());
= string.Format( string folder2ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2Name, UUID.Random());
"{0}{1}{2}", folder1Name, ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR, UUID.Random()); string itemArchiveName = InventoryArchiveWriteRequest.CreateArchiveItemName(itemName, UUID.Random());
string folder2ArchiveName
= string.Format(
"{0}{1}{2}", folder2Name, ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR, UUID.Random());
string itemArchivePath string itemArchivePath
= string.Format( = string.Format(
"{0}{1}/{2}/{3}", "{0}{1}{2}{3}",
ArchiveConstants.INVENTORY_PATH, folder1ArchiveName, folder2ArchiveName, itemName); ArchiveConstants.INVENTORY_PATH, folder1ArchiveName, folder2ArchiveName, itemArchiveName);
//Console.WriteLine("userInfo.RootFolder 2: {0}", userInfo.RootFolder); //Console.WriteLine("userInfo.RootFolder 2: {0}", userInfo.RootFolder);

View File

@ -588,10 +588,9 @@ namespace OpenSim.Region.CoreModules.World.Land
RegionConnections connectiondata, ScenePresence rootPresence) RegionConnections connectiondata, ScenePresence rootPresence)
{ {
RegionData[] rdata = connectiondata.ConnectedRegions.ToArray(); RegionData[] rdata = connectiondata.ConnectedRegions.ToArray();
List<IClientAPI> clients = new List<IClientAPI>(); //List<IClientAPI> clients = new List<IClientAPI>();
Dictionary<Vector2, RegionCourseLocationStruct> updates = new Dictionary<Vector2, RegionCourseLocationStruct>(); Dictionary<Vector2, RegionCourseLocationStruct> updates = new Dictionary<Vector2, RegionCourseLocationStruct>();
// Root Region entry // Root Region entry
RegionCourseLocationStruct rootupdatedata = new RegionCourseLocationStruct(); RegionCourseLocationStruct rootupdatedata = new RegionCourseLocationStruct();
rootupdatedata.Locations = new List<Vector3>(); rootupdatedata.Locations = new List<Vector3>();

View File

@ -1297,6 +1297,7 @@ namespace OpenSim.Region.Framework.Scenes
m_log.Warn("[TERRAIN]: Scene.cs: LoadWorldMap() - Failed with exception " + e.ToString() + " Regenerating"); 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 // 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) if ((int)Constants.RegionSize != 256)
{ {
Heightmap = new TerrainChannel(); Heightmap = new TerrainChannel();

View File

@ -3488,7 +3488,7 @@ namespace OpenSim.Region.Physics.OdePlugin
{ {
if (geom == localGround) if (geom == localGround)
{ {
localHeightfield = TerrainHeightFieldHeights[geom]; //localHeightfield = TerrainHeightFieldHeights[geom];
proceed = true; proceed = true;
} }
else else
@ -3510,7 +3510,7 @@ namespace OpenSim.Region.Physics.OdePlugin
// memory corruption // memory corruption
if (TerrainHeightFieldHeights.ContainsKey(g)) if (TerrainHeightFieldHeights.ContainsKey(g))
{ {
float[] removingHeightField = TerrainHeightFieldHeights[g]; //float[] removingHeightField = TerrainHeightFieldHeights[g];
TerrainHeightFieldHeights.Remove(g); TerrainHeightFieldHeights.Remove(g);
if (RegionTerrain.ContainsKey(g)) if (RegionTerrain.ContainsKey(g))
@ -3519,28 +3519,18 @@ namespace OpenSim.Region.Physics.OdePlugin
} }
d.GeomDestroy(g); d.GeomDestroy(g);
removingHeightField = new float[0]; //removingHeightField = new float[0];
} }
} }
} }
else else
{ {
m_log.Warn("[PHYSICS]: Couldn't proceed with UnCombine. Region has inconsistant data."); m_log.Warn("[PHYSICS]: Couldn't proceed with UnCombine. Region has inconsistant data.");
} }
} }
} }
} }
public override void SetWaterLevel(float baseheight) public override void SetWaterLevel(float baseheight)
{ {
waterlevel = baseheight; waterlevel = baseheight;

View File

@ -9477,8 +9477,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return; return;
} }
System.Text.ASCIIEncoding enc = System.Text.UTF8Encoding enc =
new System.Text.ASCIIEncoding(); new System.Text.UTF8Encoding();
string data = enc.GetString(a.Data); string data = enc.GetString(a.Data);
//m_log.Debug(data); //m_log.Debug(data);
NotecardCache.Cache(id, data); NotecardCache.Cache(id, data);
@ -9524,29 +9524,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (NotecardCache.IsCached(assetID)) if (NotecardCache.IsCached(assetID))
{ {
AsyncCommands. AsyncCommands.DataserverPlugin.DataserverReply(assetID.ToString(),
DataserverPlugin.DataserverReply(assetID.ToString(), NotecardCache.GetLine(assetID, line, m_notecardLineReadCharsMax));
NotecardCache.GetLine(assetID, line, m_notecardLineReadCharsMax));
ConditionalScriptSleep(100); ConditionalScriptSleep(100);
return tid.ToString(); return tid.ToString();
} }
WithNotecard(assetID, delegate (UUID id, AssetBase a) WithNotecard(assetID, delegate (UUID id, AssetBase a)
{ {
if (a == null || a.Type != 7) if (a == null || a.Type != 7)
{ {
ShoutError("Notecard '" + name + "' could not be found."); ShoutError("Notecard '" + name + "' could not be found.");
return; return;
} }
System.Text.ASCIIEncoding enc = System.Text.UTF8Encoding enc =
new System.Text.ASCIIEncoding(); new System.Text.UTF8Encoding();
string data = enc.GetString(a.Data); string data = enc.GetString(a.Data);
//m_log.Debug(data); //m_log.Debug(data);
NotecardCache.Cache(id, data); NotecardCache.Cache(id, data);
AsyncCommands.DataserverPlugin.DataserverReply(id.ToString(), AsyncCommands.DataserverPlugin.DataserverReply(id.ToString(),
NotecardCache.GetLine(id, line, m_notecardLineReadCharsMax)); NotecardCache.GetLine(id, line, m_notecardLineReadCharsMax));
}); });
ConditionalScriptSleep(100); ConditionalScriptSleep(100);
return tid.ToString(); return tid.ToString();

View File

@ -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 " notecardData = "Linden text version 2\n{\nLLEmbeddedItems version 1\n{\ncount 0\n}\nText length "
+ textLength.ToString() + "\n" + notecardData + "}\n"; + textLength.ToString() + "\n" + notecardData + "}\n";
asset.Data = Encoding.ASCII.GetBytes(notecardData); asset.Data = Encoding.UTF8.GetBytes(notecardData);
World.AssetService.Store(asset); World.AssetService.Store(asset);
// Create Task Entry // Create Task Entry
@ -1522,7 +1522,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
AssetBase a = World.AssetService.Get(assetID.ToString()); AssetBase a = World.AssetService.Get(assetID.ToString());
if (a != null) 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); string data = enc.GetString(a.Data);
NotecardCache.Cache(assetID, data); NotecardCache.Cache(assetID, data);
} }
@ -1575,7 +1575,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
AssetBase a = World.AssetService.Get(assetID.ToString()); AssetBase a = World.AssetService.Get(assetID.ToString());
if (a != null) 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); string data = enc.GetString(a.Data);
NotecardCache.Cache(assetID, data); NotecardCache.Cache(assetID, data);
} }
@ -1632,7 +1632,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
AssetBase a = World.AssetService.Get(assetID.ToString()); AssetBase a = World.AssetService.Get(assetID.ToString());
if (a != null) 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); string data = enc.GetString(a.Data);
NotecardCache.Cache(assetID, data); NotecardCache.Cache(assetID, data);
} }

View File

@ -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
{
/// <summary>
/// Utility functions for carrying out user inventory related tests.
/// </summary>
public static class UserInventoryTestUtils
{
public static readonly string PATH_DELIMITER = "/";
/// <summary>
/// Create inventory folders starting from the user's root folder.
/// </summary>
///
/// Ignores any existing folders with the same name
///
/// <param name="inventoryService"></param>
/// <param name="userId"></param>
/// <param name="path">
/// The folders to create. Multiple folders can be specified on a path delimited by the PATH_DELIMITER
/// </param>
/// <returns>
/// 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.
/// </returns>
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);
}
/// <summary>
/// Create inventory folders starting from a given parent folder
/// </summary>
///
/// Ignores any existing folders with the same name
///
/// <param name="inventoryService"></param>
/// <param name="parentFolder"></param>
/// <param name="path">
/// The folders to create. Multiple folders can be specified on a path delimited by the PATH_DELIMITER
/// </param>
/// <returns>
/// The folder created. If the path contains multiple folders then the last one created is returned.
/// </returns>
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;
}
}
}

View File

@ -35,7 +35,7 @@ namespace OpenSim.Tests.Common.Setup
/// <summary> /// <summary>
/// Utility functions for carrying out user profile related tests. /// Utility functions for carrying out user profile related tests.
/// </summary> /// </summary>
public class UserProfileTestUtils public static class UserProfileTestUtils
{ {
/// <summary> /// <summary>
/// Create a test user with a standard inventory /// Create a test user with a standard inventory