From b7ae8701ce6881991fbacf28cdbb0d09f220f6ec Mon Sep 17 00:00:00 2001 From: Justin Clarke Casey Date: Mon, 14 Apr 2008 18:43:23 +0000 Subject: * Working towards notifying the client if the inventory service has failed, rather than simply returning 0 items. * This is very early support which would only be triggered in a rather unlikely case (if the user server correctly received an inventory skeleton, but later on failed to return the whole inventory in a timely manner. Also, this only applies to the 1.19.1.4 client onwards * Code cleanup and support for other failure cases (failure of inventory caching on region crossing, failure to actually add a folder/item, etc, should follow. --- .../Cache/UserProfileCacheService.cs | 6 ++-- .../Framework/Communications/Capabilities/Caps.cs | 35 ++++++++++++++++++++-- OpenSim/Region/ClientStack/ClientView.cs | 9 ++++-- OpenSim/Region/Environment/Scenes/InnerScene.cs | 33 ++++++++++++++++---- OpenSim/Region/Environment/Scenes/Scene.cs | 2 +- 5 files changed, 70 insertions(+), 15 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Framework/Communications/Cache/UserProfileCacheService.cs b/OpenSim/Framework/Communications/Cache/UserProfileCacheService.cs index 7995841..f746e8b 100644 --- a/OpenSim/Framework/Communications/Cache/UserProfileCacheService.cs +++ b/OpenSim/Framework/Communications/Cache/UserProfileCacheService.cs @@ -340,7 +340,7 @@ namespace OpenSim.Framework.Communications.Cache /// /// /// - /// + /// null if the inventory look up failed public List HandleFetchInventoryDescendentsCAPS(LLUUID agentID, LLUUID folderID, LLUUID ownerID, bool fetchFolders, bool fetchItems, int sortOrder) { @@ -403,7 +403,7 @@ namespace OpenSim.Framework.Communications.Cache { m_log.ErrorFormat("[INVENTORY CACHE]: Could not find root folder for user {0}", agentID.ToString()); - return new List(); ; + return null; } } else @@ -412,7 +412,7 @@ namespace OpenSim.Framework.Communications.Cache "[USER CACHE]: HandleFetchInventoryDescendentsCAPS() Could not find user profile for {0}", agentID); - return new List(); + return null; } // If we've reached this point then we couldn't find the folder, even though the client thinks diff --git a/OpenSim/Framework/Communications/Capabilities/Caps.cs b/OpenSim/Framework/Communications/Capabilities/Caps.cs index f164208..46f50ad 100644 --- a/OpenSim/Framework/Communications/Capabilities/Caps.cs +++ b/OpenSim/Framework/Communications/Capabilities/Caps.cs @@ -56,6 +56,13 @@ namespace OpenSim.Region.Capabilities public delegate List FetchInventoryDescendentsCAPS(LLUUID agentID, LLUUID folderID, LLUUID ownerID, bool fetchFolders, bool fetchItems, int sortOrder); + + /// + /// XXX Probably not a particularly nice way of allow us to get the scene presence from the scene (chiefly so that + /// we can popup a message on the user's client if the inventory service has permanently failed). But I didn't want + /// to just pass the whole Scene into CAPS. + /// + public delegate IClientAPI GetClientDelegate(LLUUID agentID); public class Caps { @@ -99,8 +106,8 @@ namespace OpenSim.Region.Capabilities public NewInventoryItem AddNewInventoryItem = null; public ItemUpdatedCallback ItemUpdatedCall = null; public TaskScriptUpdatedCallback TaskScriptUpdatedCall = null; - // public FetchInventoryDescendentsCAPS CAPSFetchInventoryDescendents = null; + public GetClientDelegate GetClient = null; public Caps(AssetCache assetCache, BaseHttpServer httpServer, string httpListen, uint httpPort, string capsPath, LLUUID agent, bool dumpAssetsToFile) @@ -240,7 +247,7 @@ namespace OpenSim.Region.Capabilities LLSDFetchInventoryDescendents llsdRequest = new LLSDFetchInventoryDescendents(); LLSDHelpers.DeserialiseLLSDMap(inventoryhash, llsdRequest); - LLSDInventoryDescendents reply = FetchInventory(llsdRequest); + LLSDInventoryDescendents reply = FetchInventoryReply(llsdRequest); inventoryitemstr = LLSDHelpers.SerialiseLLSDReply(reply); inventoryitemstr = inventoryitemstr.Replace("folders", ""); @@ -265,7 +272,7 @@ namespace OpenSim.Region.Capabilities return response; } - private LLSDInventoryDescendents FetchInventory(LLSDFetchInventoryDescendents invFetch) + private LLSDInventoryDescendents FetchInventoryReply(LLSDFetchInventoryDescendents invFetch) { LLSDInventoryDescendents reply = new LLSDInventoryDescendents(); LLSDInventoryFolderContents contents = new LLSDInventoryFolderContents(); @@ -289,6 +296,7 @@ namespace OpenSim.Region.Capabilities { itemList = CAPSFetchInventoryDescendents(m_agentID, invFetch.folder_id, invFetch.owner_id, invFetch.fetch_folders, invFetch.fetch_items, invFetch.sort_order); } + if (itemList != null) { foreach (InventoryItemBase invItem in itemList) @@ -296,6 +304,27 @@ namespace OpenSim.Region.Capabilities contents.items.Array.Add(ConvertInventoryItem(invItem)); } } + else + { + IClientAPI client = GetClient(m_agentID); + + // We're going to both notify the client of inventory service failure and send back a 'no folder contents' response. + // If we don't send back the response, + // the client becomes unhappy (see Teravus' comment in FetchInventoryRequest()) + if (client != null) + { + client.SendAgentAlertMessage( + "AGIN0001E: The inventory service has either failed or is not responding. Your inventory will not function properly for the rest of this session. Please clear your cache and relog.", + true); + } + else + { + m_log.ErrorFormat( + "[AGENT INVENTORY]: Could not lookup controlling client for {0} in order to notify them of the inventory service failure", + m_agentID); + } + } + contents.descendents = contents.items.Array.Count; return reply; } diff --git a/OpenSim/Region/ClientStack/ClientView.cs b/OpenSim/Region/ClientStack/ClientView.cs index 2599456..6ba40df 100644 --- a/OpenSim/Region/ClientStack/ClientView.cs +++ b/OpenSim/Region/ClientStack/ClientView.cs @@ -1576,7 +1576,8 @@ namespace OpenSim.Region.ClientStack } /// - /// + /// Send an alert message to the client. On the Linden client (tested 1.19.1.4), this pops up a brief duration + /// blue information box in the bottom right hand corner. /// /// public void SendAlertMessage(string message) @@ -1587,10 +1588,12 @@ namespace OpenSim.Region.ClientStack } /// - /// + /// Send an agent alert message to the client. /// /// - /// + /// On the linden client, if this true then it displays a one button text box placed in the + /// middle of the window. If false, the message is displayed in a brief duration blue information box (as for + /// the AlertMessage packet). public void SendAgentAlertMessage(string message, bool modal) { AgentAlertMessagePacket alertPack = (AgentAlertMessagePacket)PacketPool.Instance.GetPacket(PacketType.AgentAlertMessage); diff --git a/OpenSim/Region/Environment/Scenes/InnerScene.cs b/OpenSim/Region/Environment/Scenes/InnerScene.cs index ef98599..0838387 100644 --- a/OpenSim/Region/Environment/Scenes/InnerScene.cs +++ b/OpenSim/Region/Environment/Scenes/InnerScene.cs @@ -618,6 +618,28 @@ namespace OpenSim.Region.Environment.Scenes return result; } + + /// + /// Get the controlling client for the given avatar, if there is one. + /// + /// FIXME: The only user of the method right now is Caps.cs, in order to resolve a client API since it can't + /// use the ScenePresence. This could be better solved in a number of ways - we could establish an + /// OpenSim.Framework.IScenePresence, or move the caps code into a region package (which might be the more + /// suitable solution). + /// + /// + /// null if either the avatar wasn't in the scene, or they do not have a controlling client + public IClientAPI GetControllingClient(LLUUID agentId) + { + ScenePresence presence = GetScenePresence(agentId); + + if (presence != null) + { + return presence.ControllingClient; + } + + return null; + } /// /// Request a filtered list of m_scenePresences in this World @@ -640,16 +662,17 @@ namespace OpenSim.Region.Environment.Scenes } /// - /// Request a Avatar by UUID + /// Request a scene presence by UUID /// /// - /// - public ScenePresence GetScenePresence(LLUUID avatarID) + /// null if the agent was not found + public ScenePresence GetScenePresence(LLUUID agentID) { - if (ScenePresences.ContainsKey(avatarID)) + if (ScenePresences.ContainsKey(agentID)) { - return ScenePresences[avatarID]; + return ScenePresences[agentID]; } + return null; } diff --git a/OpenSim/Region/Environment/Scenes/Scene.cs b/OpenSim/Region/Environment/Scenes/Scene.cs index 410120f..b93367c 100644 --- a/OpenSim/Region/Environment/Scenes/Scene.cs +++ b/OpenSim/Region/Environment/Scenes/Scene.cs @@ -1884,7 +1884,7 @@ namespace OpenSim.Region.Environment.Scenes cap.ItemUpdatedCall = CapsUpdateInventoryItemAsset; cap.TaskScriptUpdatedCall = CapsUpdateTaskInventoryScriptAsset; cap.CAPSFetchInventoryDescendents = CommsManager.UserProfileCacheService.HandleFetchInventoryDescendentsCAPS; - + cap.GetClient = m_innerScene.GetControllingClient; m_capsHandlers[agentId] = cap; } -- cgit v1.1