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 +++++++++++++
2 files changed, 90 insertions(+), 8 deletions(-)
(limited to 'OpenSim/Framework/Communications')
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);
+ }
+ }
}
--
cgit v1.1