From 10b2a4597abb4b51ba3584daf3c837f6c5033ded Mon Sep 17 00:00:00 2001
From: Melanie Thielker
Date: Thu, 28 Aug 2008 20:56:53 +0000
Subject: Mantis #1903 Thank you, cmickeyb, for a patch that fixes inventory
folder retrieval.
---
.../Communications/Cache/CachedUserInfo.cs | 140 +++++++++------------
1 file changed, 59 insertions(+), 81 deletions(-)
(limited to 'OpenSim/Framework/Communications')
diff --git a/OpenSim/Framework/Communications/Cache/CachedUserInfo.cs b/OpenSim/Framework/Communications/Cache/CachedUserInfo.cs
index 3a20b9e..8e3be81 100644
--- a/OpenSim/Framework/Communications/Cache/CachedUserInfo.cs
+++ b/OpenSim/Framework/Communications/Cache/CachedUserInfo.cs
@@ -84,12 +84,6 @@ namespace OpenSim.Framework.Communications.Cache
public InventoryFolderImpl RootFolder { get { return m_rootFolder; } }
private InventoryFolderImpl m_rootFolder;
- ///
- /// FIXME: This could be contained within a local variable - it doesn't need to be a field
- ///
- private IDictionary> pendingCategorizationFolders
- = new Dictionary>();
-
public LLUUID SessionID
{
get { return m_session_id; }
@@ -130,55 +124,58 @@ namespace OpenSim.Framework.Communications.Cache
}
///
- /// Store a folder pending arrival of its parent
+ /// Helper function for InventoryReceive() - Store a folder temporarily until we've received entire folder list
///
///
- private void AddPendingFolder(InventoryFolderImpl folder)
+ private void AddFolderToDictionary(InventoryFolderImpl folder, IDictionary> dictionary)
{
LLUUID parentFolderId = folder.ParentID;
- if (pendingCategorizationFolders.ContainsKey(parentFolderId))
- {
- pendingCategorizationFolders[parentFolderId].Add(folder);
- }
+ if (dictionary.ContainsKey(parentFolderId))
+ dictionary[parentFolderId].Add(folder);
else
{
IList folders = new List();
folders.Add(folder);
-
- pendingCategorizationFolders[parentFolderId] = folders;
+ dictionary[parentFolderId] = folders;
}
}
///
- /// Add any pending folders which were received before the given folder
+ /// Recursively, in depth-first order, add all the folders we've received (stored
+ /// in a dictionary indexed by parent ID) into the tree that describes user folder
+ /// heirarchy
///
///
/// A
///
- private void ResolvePendingFolders(InventoryFolderImpl newFolder)
+ private void ResolveReceivedFolders(InventoryFolderImpl parentFolder, IDictionary> folderDictionary)
{
- if (pendingCategorizationFolders.ContainsKey(newFolder.ID))
+ if (folderDictionary.ContainsKey(parentFolder.ID))
{
List resolvedFolders = new List(); // Folders we've resolved with this invocation
- foreach (InventoryFolderImpl folder in pendingCategorizationFolders[newFolder.ID])
+ foreach (InventoryFolderImpl folder in folderDictionary[parentFolder.ID])
{
- // m_log.DebugFormat(
- // "[INVENTORY CACHE]: Resolving pending received folder {0} {1} into {2} {3}",
- // folder.name, folder.folderID, parent.name, parent.folderID);
- lock (newFolder.SubFolders)
+ lock (parentFolder.SubFolders)
{
- if (!newFolder.SubFolders.ContainsKey(folder.ID))
+ if (parentFolder.SubFolders.ContainsKey(folder.ID))
+ {
+ m_log.WarnFormat(
+ "[INVENTORY CACHE]: Received folder {0} {1} from inventory service which has already been received",
+ folder.Name, folder.ID);
+ }
+ else
{
resolvedFolders.Add(folder);
- newFolder.SubFolders.Add(folder.ID, folder);
+ parentFolder.SubFolders.Add(folder.ID, folder);
}
}
- }
- pendingCategorizationFolders.Remove(newFolder.ID);
+ } // foreach (folder in pendingCategorizationFolders[parentFolder.ID])
+
+ folderDictionary.Remove(parentFolder.ID);
foreach (InventoryFolderImpl folder in resolvedFolders)
- ResolvePendingFolders(folder);
+ ResolveReceivedFolders(folder, folderDictionary);
}
}
@@ -204,25 +201,56 @@ namespace OpenSim.Framework.Communications.Cache
///
public void InventoryReceive(ICollection folders, ICollection items)
{
+
// FIXME: Exceptions thrown upwards never appear on the console. Could fix further up if these
// are simply being swallowed
try
{
+ // collection of all received folders, indexed by their parent ID
+ IDictionary> receivedFolders =
+ new Dictionary>();
+
+ // Take all received folders, find the root folder, and put ther rest into
+ // the pendingCategorizationFolders collection
foreach (InventoryFolderImpl folder in folders)
+ AddFolderToDictionary(folder, receivedFolders);
+
+ if (!receivedFolders.ContainsKey(LLUUID.Zero))
+ throw new Exception("Database did not return a root inventory folder");
+ else
{
- FolderReceive(folder);
+ IList rootFolderList = receivedFolders[LLUUID.Zero];
+ m_rootFolder = rootFolderList[0];
+ if (rootFolderList.Count > 1)
+ {
+ for (int i = 1; i < rootFolderList.Count; i++)
+ {
+ m_log.WarnFormat(
+ "[INVENTORY CACHE]: Discarding extra root folder {0}. Using previously received root folder {1}",
+ rootFolderList[i].ID, RootFolder.ID);
+ }
+ }
+ receivedFolders.Remove(LLUUID.Zero);
}
+
+ // Now take the pendingCategorizationFolders collection, and turn that into a tree,
+ // with the root being RootFolder
+ if (RootFolder != null)
+ ResolveReceivedFolders(RootFolder, receivedFolders);
+
// Generate a warning for folders that are not part of the heirarchy
- foreach ( KeyValuePair> folderList in pendingCategorizationFolders)
+ foreach (KeyValuePair> folderList in receivedFolders)
{
foreach (InventoryFolderImpl folder in folderList.Value)
m_log.WarnFormat("[INVENTORY CACHE]: Malformed Database: Unresolved Pending Folder {0}", folder.Name);
}
+
+ // Take all ther received items and put them into the folder tree heirarchy
+ // TBD: This operation is O(n^2), if we made a dictionary of all folders indexed by their ID, we could make
+ // this O(n)
foreach (InventoryItemBase item in items)
- {
ItemReceive(item);
- }
}
catch (Exception e)
{
@@ -244,56 +272,6 @@ namespace OpenSim.Framework.Communications.Cache
}
///
- /// Callback invoked when a folder is received from an async request to the inventory service.
- ///
- ///
- ///
- private void FolderReceive(InventoryFolderImpl newFolder)
- {
- // m_log.DebugFormat(
- // "[INVENTORY CACHE]: Received folder {0} {1} for user {2}",
- // folderInfo.Name, folderInfo.ID, userID);
-
- if (RootFolder == null)
- {
- if (newFolder.ParentID == LLUUID.Zero)
- {
- m_rootFolder = newFolder;
- }
- else
- {
- AddPendingFolder(newFolder);
- }
- }
- else
- {
- InventoryFolderImpl parentFolder = RootFolder.FindFolder(newFolder.ParentID);
-
- if (parentFolder == null)
- {
- AddPendingFolder(newFolder);
- }
- else
- {
- lock (parentFolder.SubFolders)
- {
- if (!parentFolder.SubFolders.ContainsKey(newFolder.ID))
- {
- parentFolder.SubFolders.Add(newFolder.ID, newFolder);
- }
- else
- {
- m_log.WarnFormat(
- "[INVENTORY CACHE]: Received folder {0} {1} from inventory service which has already been received",
- newFolder.Name, newFolder.ID);
- }
- }
- }
- }
- ResolvePendingFolders(newFolder);
- }
-
- ///
/// Callback invoked when an item is received from an async request to the inventory service.
///
/// We're assuming here that items are always received after all the folders
--
cgit v1.1