From 269a2e4b887b9841309d4472508b19324a91d80d Mon Sep 17 00:00:00 2001 From: Justin Clarke Casey Date: Tue, 22 Apr 2008 17:24:13 +0000 Subject: * Allow folder renaming to complete after an agent inventory has been received by a region from the inventory service * This replaces the old behaviour of failing straight away, which could cause lost updates if the inventory service was slow in responding * This is the first baby step to making all inventory requests behave this way, to reduce inventory lossage --- .../Communications/Cache/CachedUserInfo.cs | 62 +++++++++++++++++++--- .../Cache/UserProfileCacheService.cs | 36 +++++++++++++ .../Servers/SynchronousRestObjectPoster.cs | 2 +- 3 files changed, 91 insertions(+), 9 deletions(-) (limited to 'OpenSim/Framework') diff --git a/OpenSim/Framework/Communications/Cache/CachedUserInfo.cs b/OpenSim/Framework/Communications/Cache/CachedUserInfo.cs index a245af1..3d7ada3 100644 --- a/OpenSim/Framework/Communications/Cache/CachedUserInfo.cs +++ b/OpenSim/Framework/Communications/Cache/CachedUserInfo.cs @@ -45,25 +45,31 @@ namespace OpenSim.Framework.Communications.Cache /// The comms manager holds references to services (user, grid, inventory, etc.) /// private readonly CommunicationsManager m_commsManager; - - private UserProfileData m_userProfile; + public UserProfileData UserProfile { get { return m_userProfile; } } + private UserProfileData m_userProfile; - + /// + /// Has we received the user's inventory from the inventory service? + /// private bool m_hasInventory; /// + /// Inventory requests waiting for receipt of this user's inventory from the inventory service. + /// + private readonly IList m_pendingRequests = new List(); + + /// /// Has this user info object yet received its inventory information from the invetnroy service? /// public bool HasInventory { get { return m_hasInventory; } } - // FIXME: These need to be hidden behind accessors private InventoryFolderImpl m_rootFolder; public InventoryFolderImpl RootFolder { get { return m_rootFolder; } } /// - /// Stores received folders for which we have not yet received the parents. - /// + /// FIXME: This could be contained within a local variable - it doesn't need to be a field + /// private IDictionary> pendingCategorizationFolders = new Dictionary>(); @@ -79,6 +85,27 @@ namespace OpenSim.Framework.Communications.Cache } /// + /// This allows a request to be added to be processed once we receive a user's inventory + /// from the inventory service. If we already have the inventory, the request + /// is executed immediately instead. + /// + /// + public void AddRequest(IInventoryRequest request) + { + lock (m_pendingRequests) + { + if (m_hasInventory) + { + request.Execute(); + } + else + { + m_pendingRequests.Add(request); + } + } + } + + /// /// Store a folder pending categorization when its parent is received. /// /// @@ -148,8 +175,19 @@ namespace OpenSim.Framework.Communications.Cache { m_log.ErrorFormat("[INVENTORY CACHE]: Error processing inventory received from inventory service, {0}", e); } - - m_hasInventory = true; + + // Deal with pending requests + lock (m_pendingRequests) + { + // We're going to change inventory status within the lock to avoid a race condition + // where requests are processed after the AddRequest() method has been called. + m_hasInventory = true; + + foreach (IInventoryRequest request in m_pendingRequests) + { + request.Execute(); + } + } } /// @@ -288,4 +326,12 @@ namespace OpenSim.Framework.Communications.Cache return result; } } + + /// + /// Should be implemented by callers which require a callback when the user's inventory is received + /// + public interface IInventoryRequest + { + void Execute(); + } } diff --git a/OpenSim/Framework/Communications/Cache/UserProfileCacheService.cs b/OpenSim/Framework/Communications/Cache/UserProfileCacheService.cs index bf8ff40..cbf2ded 100644 --- a/OpenSim/Framework/Communications/Cache/UserProfileCacheService.cs +++ b/OpenSim/Framework/Communications/Cache/UserProfileCacheService.cs @@ -201,6 +201,9 @@ namespace OpenSim.Framework.Communications.Cache public void HandleUpdateInventoryFolder(IClientAPI remoteClient, LLUUID folderID, ushort type, string name, LLUUID parentID) { +// m_log.DebugFormat( +// "[AGENT INVENTORY] Updating inventory folder {0} {1} for {2} {3}", folderID, name, remoteClient.Name, remoteClient.AgentId); + CachedUserInfo userProfile; if (m_userProfiles.TryGetValue(remoteClient.AgentId, out userProfile)) @@ -216,6 +219,10 @@ namespace OpenSim.Framework.Communications.Cache baseFolder.Version = userProfile.RootFolder.Version; m_commsManager.InventoryService.AddNewInventoryFolder(remoteClient.AgentId, baseFolder); } + else + { + userProfile.AddRequest(new UpdateFolderRequest(this, remoteClient, folderID, type, name, parentID)); + } } } @@ -492,4 +499,33 @@ namespace OpenSim.Framework.Communications.Cache } } } + + /// + /// Used to create an update folder request if we haven't yet received the user's inventory + /// + internal class UpdateFolderRequest : IInventoryRequest + { + private UserProfileCacheService m_userProfileCacheService; + private IClientAPI m_client; + private LLUUID m_folderID; + private ushort m_type; + private string m_name; + private LLUUID m_parentID; + + internal UpdateFolderRequest( + UserProfileCacheService cacheService, IClientAPI client, LLUUID folderID, ushort type, string name, LLUUID parentID) + { + m_userProfileCacheService = cacheService; + m_client = client; + m_folderID = folderID; + m_type = type; + m_name = name; + m_parentID = parentID; + } + + public void Execute() + { + m_userProfileCacheService.HandleUpdateInventoryFolder(m_client, m_folderID, m_type, m_name, m_parentID); + } + } } diff --git a/OpenSim/Framework/Servers/SynchronousRestObjectPoster.cs b/OpenSim/Framework/Servers/SynchronousRestObjectPoster.cs index 1b8e4ea..103fbe5 100644 --- a/OpenSim/Framework/Servers/SynchronousRestObjectPoster.cs +++ b/OpenSim/Framework/Servers/SynchronousRestObjectPoster.cs @@ -75,7 +75,7 @@ namespace OpenSim.Framework.Servers using (WebResponse resp = request.GetResponse()) { XmlSerializer deserializer = new XmlSerializer(typeof (TResponse)); - deserial = (TResponse) deserializer.Deserialize(resp.GetResponseStream()); + deserial = (TResponse) deserializer.Deserialize(resp.GetResponseStream()); } return deserial; } -- cgit v1.1