From a5176c2e2c4d2791ec15a22db4309bb15bc3ae98 Mon Sep 17 00:00:00 2001 From: Justin Clarke Casey Date: Fri, 11 Apr 2008 18:13:10 +0000 Subject: [PATCH] * Change inventory async response deliver to deliver all items and folders at once, rather than each individual * This is required in order to work towards eliminating some inventory race conditions and to better deal with situations where a grid inventory server is slow or not responding. --- .../Communications/Cache/CachedUserInfo.cs | 111 ++++++++++++------ .../Cache/UserProfileCacheService.cs | 16 ++- .../Communications/IInventoryServices.cs | 19 ++- .../Communications/InventoryServiceBase.cs | 5 +- OpenSim/Framework/InventoryCollection.cs | 3 + .../InventoryServer/GridInventoryService.cs | 3 +- .../Local/LocalInventoryService.cs | 45 +++---- .../OGS1/OGS1InventoryService.cs | 40 ++++--- 8 files changed, 152 insertions(+), 90 deletions(-) diff --git a/OpenSim/Framework/Communications/Cache/CachedUserInfo.cs b/OpenSim/Framework/Communications/Cache/CachedUserInfo.cs index 1208605d89..cf701cbd41 100644 --- a/OpenSim/Framework/Communications/Cache/CachedUserInfo.cs +++ b/OpenSim/Framework/Communications/Cache/CachedUserInfo.cs @@ -118,64 +118,82 @@ namespace OpenSim.Framework.Communications.Cache } } } + + /// + /// Callback invoked when the inventory is received from an async request to the inventory service + /// + /// + /// + public void InventoryReceive(LLUUID userID, ICollection folders, ICollection items) + { + // FIXME: Exceptions thrown upwards never appear on the console. Could fix further up if these + // are simply being swallowed + try + { + foreach (InventoryFolderImpl folder in folders) + { + FolderReceive(userID, folder); + } + + foreach (InventoryItemBase item in items) + { + ItemReceive(userID, item); + } + } + catch (Exception e) + { + m_log.ErrorFormat("[INVENTORY CACHE]: {0}", e); + } + } /// /// Callback invoked when a folder is received from an async request to the inventory service. /// /// /// - public void FolderReceive(LLUUID userID, InventoryFolderImpl folderInfo) + private void FolderReceive(LLUUID userID, InventoryFolderImpl folderInfo) { - // FIXME: Exceptions thrown upwards never appear on the console. Could fix further up if these - // are simply being swallowed - try - { // m_log.DebugFormat( // "[INVENTORY CACHE]: Received folder {0} {1} for user {2}", // folderInfo.name, folderInfo.folderID, userID); - - if (userID == UserProfile.ID) + + if (userID == UserProfile.ID) + { + if (RootFolder == null) { - if (RootFolder == null) + if (folderInfo.ParentID == LLUUID.Zero) { - if (folderInfo.ParentID == LLUUID.Zero) - { - m_rootFolder = folderInfo; - } + m_rootFolder = folderInfo; } - else if (RootFolder.ID == folderInfo.ParentID) + } + else if (RootFolder.ID == folderInfo.ParentID) + { + if (!RootFolder.SubFolders.ContainsKey(folderInfo.ID)) { - if (!RootFolder.SubFolders.ContainsKey(folderInfo.ID)) - { - RootFolder.SubFolders.Add(folderInfo.ID, folderInfo); - } - else - { - AddPendingFolder(folderInfo); - } + RootFolder.SubFolders.Add(folderInfo.ID, folderInfo); } else { - InventoryFolderImpl folder = RootFolder.HasSubFolder(folderInfo.ParentID); - if (folder != null) + AddPendingFolder(folderInfo); + } + } + else + { + InventoryFolderImpl folder = RootFolder.HasSubFolder(folderInfo.ParentID); + if (folder != null) + { + if (!folder.SubFolders.ContainsKey(folderInfo.ID)) { - if (!folder.SubFolders.ContainsKey(folderInfo.ID)) - { - folder.SubFolders.Add(folderInfo.ID, folderInfo); - } - } - else - { - AddPendingFolder(folderInfo); + folder.SubFolders.Add(folderInfo.ID, folderInfo); } } - - ResolvePendingFolders(folderInfo); + else + { + AddPendingFolder(folderInfo); + } } - } - catch (Exception e) - { - m_log.ErrorFormat("[INVENTORY CACHE] {0}", e); + + ResolvePendingFolders(folderInfo); } } @@ -187,7 +205,7 @@ namespace OpenSim.Framework.Communications.Cache /// /// /// - public void ItemReceive(LLUUID userID, InventoryItemBase itemInfo) + private void ItemReceive(LLUUID userID, InventoryItemBase itemInfo) { if ((userID == UserProfile.ID) && (RootFolder != null)) { @@ -212,6 +230,11 @@ namespace OpenSim.Framework.Communications.Cache } } + /// + /// Add an item to the user's inventory + /// + /// + /// public void AddItem(LLUUID userID, InventoryItemBase itemInfo) { if ((userID == UserProfile.ID) && HasInventory) @@ -221,6 +244,11 @@ namespace OpenSim.Framework.Communications.Cache } } + /// + /// Update an item in the user's inventory + /// + /// + /// public void UpdateItem(LLUUID userID, InventoryItemBase itemInfo) { if ((userID == UserProfile.ID) && HasInventory) @@ -229,6 +257,12 @@ namespace OpenSim.Framework.Communications.Cache } } + /// + /// Delete an item from the user's inventory + /// + /// + /// + /// public bool DeleteItem(LLUUID userID, InventoryItemBase item) { bool result = false; @@ -240,6 +274,7 @@ namespace OpenSim.Framework.Communications.Cache m_commsManager.InventoryService.DeleteInventoryItem(userID, item); } } + return result; } } diff --git a/OpenSim/Framework/Communications/Cache/UserProfileCacheService.cs b/OpenSim/Framework/Communications/Cache/UserProfileCacheService.cs index b924d5c673..6b09e01e04 100644 --- a/OpenSim/Framework/Communications/Cache/UserProfileCacheService.cs +++ b/OpenSim/Framework/Communications/Cache/UserProfileCacheService.cs @@ -97,7 +97,7 @@ namespace OpenSim.Framework.Communications.Cache CachedUserInfo userInfo = GetUserDetails(userID); if (userInfo != null) { - m_commsManager.InventoryService.RequestInventoryForUser(userID, userInfo.FolderReceive, userInfo.ItemReceive); + m_commsManager.InventoryService.RequestInventoryForUser(userID, userInfo.InventoryReceive); } else { @@ -118,6 +118,14 @@ namespace OpenSim.Framework.Communications.Cache return null; } + /// + /// Handle an inventory folder creation request from the client. + /// + /// + /// + /// + /// + /// public void HandleCreateInventoryFolder(IClientAPI remoteClient, LLUUID folderID, ushort folderType, string folderName, LLUUID parentID) { @@ -189,6 +197,12 @@ namespace OpenSim.Framework.Communications.Cache } } + /// + /// Handle an inventory folder move request from the client. + /// + /// + /// + /// public void HandleMoveInventoryFolder(IClientAPI remoteClient, LLUUID folderID, LLUUID parentID) { CachedUserInfo userProfile; diff --git a/OpenSim/Framework/Communications/IInventoryServices.cs b/OpenSim/Framework/Communications/IInventoryServices.cs index ecc6c710df..40e7ffd8ba 100644 --- a/OpenSim/Framework/Communications/IInventoryServices.cs +++ b/OpenSim/Framework/Communications/IInventoryServices.cs @@ -26,21 +26,34 @@ */ using System.Collections.Generic; + using libsecondlife; + using OpenSim.Framework.Communications.Cache; namespace OpenSim.Framework.Communications { - public delegate void InventoryFolderInfo(LLUUID userID, InventoryFolderImpl folderInfo); + /// + /// Callback used when a user's inventory is received from the inventory service + /// + public delegate void InventoryReceiptCallback(LLUUID userId, ICollection folders, ICollection items); + + //public delegate void InventoryFolderInfo(LLUUID userID, InventoryFolderImpl folderInfo); - public delegate void InventoryItemInfo(LLUUID userID, InventoryItemBase itemInfo); + //public delegate void InventoryItemInfo(LLUUID userID, InventoryItemBase itemInfo); /// /// Defines all the operations one can perform on a user's inventory. /// public interface IInventoryServices { - void RequestInventoryForUser(LLUUID userID, InventoryFolderInfo folderCallBack, InventoryItemInfo itemCallBack); + /// + /// Request the inventory for a user. This is an asynchronous operation that will call the callback when the + /// inventory has been received + /// + /// + /// + void RequestInventoryForUser(LLUUID userID, InventoryReceiptCallback callback); /// /// Add a new folder to the given user's inventory diff --git a/OpenSim/Framework/Communications/InventoryServiceBase.cs b/OpenSim/Framework/Communications/InventoryServiceBase.cs index e50e19e0a3..aedf4b3c5d 100644 --- a/OpenSim/Framework/Communications/InventoryServiceBase.cs +++ b/OpenSim/Framework/Communications/InventoryServiceBase.cs @@ -158,8 +158,9 @@ namespace OpenSim.Framework.Communications return false; } - public abstract void RequestInventoryForUser(LLUUID userID, InventoryFolderInfo folderCallBack, - InventoryItemInfo itemCallBack); + // See IInventoryServices + public abstract void RequestInventoryForUser(LLUUID userID, InventoryReceiptCallback callback); + public abstract void AddNewInventoryFolder(LLUUID userID, InventoryFolderBase folder); public abstract void MoveExistingInventoryFolder(InventoryFolderBase folder); public abstract void AddNewInventoryItem(LLUUID userID, InventoryItemBase item); diff --git a/OpenSim/Framework/InventoryCollection.cs b/OpenSim/Framework/InventoryCollection.cs index c8d8716093..e76e1a99ed 100644 --- a/OpenSim/Framework/InventoryCollection.cs +++ b/OpenSim/Framework/InventoryCollection.cs @@ -32,6 +32,9 @@ using libsecondlife; namespace OpenSim.Framework { + /// + /// Used to serialize a whole inventory for transfer over the network. + /// public class InventoryCollection { public List _folders; diff --git a/OpenSim/Grid/InventoryServer/GridInventoryService.cs b/OpenSim/Grid/InventoryServer/GridInventoryService.cs index 1ae52434e3..72d43d4a4c 100644 --- a/OpenSim/Grid/InventoryServer/GridInventoryService.cs +++ b/OpenSim/Grid/InventoryServer/GridInventoryService.cs @@ -41,8 +41,7 @@ namespace OpenSim.Grid.InventoryServer { private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - public override void RequestInventoryForUser(LLUUID userID, InventoryFolderInfo folderCallBack, - InventoryItemInfo itemCallBack) + public override void RequestInventoryForUser(LLUUID userID, InventoryReceiptCallback callback) { } diff --git a/OpenSim/Region/Communications/Local/LocalInventoryService.cs b/OpenSim/Region/Communications/Local/LocalInventoryService.cs index bb3db9dd03..13cb6de02b 100644 --- a/OpenSim/Region/Communications/Local/LocalInventoryService.cs +++ b/OpenSim/Region/Communications/Local/LocalInventoryService.cs @@ -39,32 +39,38 @@ namespace OpenSim.Region.Communications.Local /// public class LocalInventoryService : InventoryServiceBase { - public override void RequestInventoryForUser(LLUUID userID, InventoryFolderInfo folderCallBack, - InventoryItemInfo itemCallBack) + public override void RequestInventoryForUser(LLUUID userID, InventoryReceiptCallback callback) { - List folders = GetInventorySkeleton(userID); - + List skeletonFolders = GetInventorySkeleton(userID); InventoryFolderImpl rootFolder = null; + + ICollection folders = new List(); + ICollection items = new List(); - //need to make sure we send root folder first - foreach (InventoryFolderBase folder in folders) + // Need to retrieve the root folder on the first pass + foreach (InventoryFolderBase folder in skeletonFolders) { if (folder.ParentID == LLUUID.Zero) { - rootFolder = RequestInventoryFolder(userID, folder, folderCallBack, itemCallBack); + //rootFolder = RequestInventoryFolder(userID, folder, callback); + rootFolder = new InventoryFolderImpl(folder); + folders.Add(rootFolder); } } if (rootFolder != null) { - foreach (InventoryFolderBase folder in folders) + foreach (InventoryFolderBase folder in skeletonFolders) { if (folder.ID != rootFolder.ID) { - RequestInventoryFolder(userID, folder, folderCallBack, itemCallBack); + //RequestInventoryFolder(userID, folder, callback); + folders.Add(new InventoryFolderImpl(folder)); } } } + + callback(userID, folders, items); } public override void AddNewInventoryFolder(LLUUID userID, InventoryFolderBase folder) @@ -99,26 +105,5 @@ namespace OpenSim.Region.Communications.Local return true; } } - - /// - /// Send the given inventory folder and its item contents back to the requester. - /// - /// - /// - private InventoryFolderImpl RequestInventoryFolder(LLUUID userID, InventoryFolderBase folder, - InventoryFolderInfo folderCallBack, - InventoryItemInfo itemCallBack) - { - InventoryFolderImpl newFolder = new InventoryFolderImpl(folder); - folderCallBack(userID, newFolder); - - List items = RequestFolderItems(newFolder.ID); - foreach (InventoryItemBase item in items) - { - itemCallBack(userID, item); - } - - return newFolder; - } } } diff --git a/OpenSim/Region/Communications/OGS1/OGS1InventoryService.cs b/OpenSim/Region/Communications/OGS1/OGS1InventoryService.cs index b18c5bf071..f31127f616 100644 --- a/OpenSim/Region/Communications/OGS1/OGS1InventoryService.cs +++ b/OpenSim/Region/Communications/OGS1/OGS1InventoryService.cs @@ -51,12 +51,11 @@ namespace OpenSim.Region.Communications.OGS1 #region IInventoryServices Members // See IInventoryServices - public void RequestInventoryForUser(LLUUID userID, InventoryFolderInfo folderCallBack, - InventoryItemInfo itemCallBack) + public void RequestInventoryForUser(LLUUID userID, InventoryReceiptCallback callback) { if (!m_RequestingInventory.ContainsKey(userID)) { - InventoryRequest request = new InventoryRequest(userID, folderCallBack, itemCallBack); + InventoryRequest request = new InventoryRequest(userID, callback); m_RequestingInventory.Add(userID, request); RequestInventory(userID); } @@ -105,13 +104,17 @@ namespace OpenSim.Region.Communications.OGS1 InventoryFolderImpl rootFolder = null; InventoryRequest request = m_RequestingInventory[userID]; + + ICollection folders = new List(); + ICollection items = new List(); + foreach (InventoryFolderBase folder in response.Folders) { if (folder.ParentID == LLUUID.Zero) { - InventoryFolderImpl newfolder = new InventoryFolderImpl(folder); - rootFolder = newfolder; - request.FolderCallBack(userID, newfolder); + rootFolder = new InventoryFolderImpl(folder); + folders.Add(rootFolder); + //request.FolderCallBack(userID, newfolder); } } @@ -121,16 +124,20 @@ namespace OpenSim.Region.Communications.OGS1 { if (folder.ID != rootFolder.ID) { - InventoryFolderImpl newfolder = new InventoryFolderImpl(folder); - request.FolderCallBack(userID, newfolder); + folders.Add(new InventoryFolderImpl(folder)); + //request.FolderCallBack(userID, newfolder); } } foreach (InventoryItemBase item in response.AllItems) { - request.ItemCallBack(userID, item); + items.Add(item); + //request.ItemCallBack(userID, item); } } + + request.Callback(userID, folders, items); + m_RequestingInventory.Remove(userID); } else @@ -223,17 +230,22 @@ namespace OpenSim.Region.Communications.OGS1 #endregion + /// + /// Caches a pending inventory request that has yet to be satisfied by the inventory service + /// public class InventoryRequest { public LLUUID UserID; - public InventoryFolderInfo FolderCallBack; - public InventoryItemInfo ItemCallBack; + public InventoryReceiptCallback Callback; + //public InventoryFolderInfo FolderCallBack; + //public InventoryItemInfo ItemCallBack; - public InventoryRequest(LLUUID userId, InventoryFolderInfo folderCall, InventoryItemInfo itemCall) + public InventoryRequest(LLUUID userId, InventoryReceiptCallback callback) { UserID = userId; - FolderCallBack = folderCall; - ItemCallBack = itemCall; + //FolderCallBack = folderCall; + //ItemCallBack = itemCall; + Callback = callback; } } }