* 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.0.6.0-stable
parent
e21886eea0
commit
b7ae8701ce
|
@ -340,7 +340,7 @@ namespace OpenSim.Framework.Communications.Cache
|
||||||
/// <param name="fetchFolders"></param>
|
/// <param name="fetchFolders"></param>
|
||||||
/// <param name="fetchItems"></param>
|
/// <param name="fetchItems"></param>
|
||||||
/// <param name="sortOrder"></param>
|
/// <param name="sortOrder"></param>
|
||||||
/// <returns></returns>
|
/// <returns>null if the inventory look up failed</returns>
|
||||||
public List<InventoryItemBase> HandleFetchInventoryDescendentsCAPS(LLUUID agentID, LLUUID folderID, LLUUID ownerID,
|
public List<InventoryItemBase> HandleFetchInventoryDescendentsCAPS(LLUUID agentID, LLUUID folderID, LLUUID ownerID,
|
||||||
bool fetchFolders, bool fetchItems, int sortOrder)
|
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());
|
m_log.ErrorFormat("[INVENTORY CACHE]: Could not find root folder for user {0}", agentID.ToString());
|
||||||
|
|
||||||
return new List<InventoryItemBase>(); ;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -412,7 +412,7 @@ namespace OpenSim.Framework.Communications.Cache
|
||||||
"[USER CACHE]: HandleFetchInventoryDescendentsCAPS() Could not find user profile for {0}",
|
"[USER CACHE]: HandleFetchInventoryDescendentsCAPS() Could not find user profile for {0}",
|
||||||
agentID);
|
agentID);
|
||||||
|
|
||||||
return new List<InventoryItemBase>();
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we've reached this point then we couldn't find the folder, even though the client thinks
|
// If we've reached this point then we couldn't find the folder, even though the client thinks
|
||||||
|
|
|
@ -57,6 +57,13 @@ namespace OpenSim.Region.Capabilities
|
||||||
public delegate List<InventoryItemBase> FetchInventoryDescendentsCAPS(LLUUID agentID, LLUUID folderID, LLUUID ownerID,
|
public delegate List<InventoryItemBase> FetchInventoryDescendentsCAPS(LLUUID agentID, LLUUID folderID, LLUUID ownerID,
|
||||||
bool fetchFolders, bool fetchItems, int sortOrder);
|
bool fetchFolders, bool fetchItems, int sortOrder);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 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.
|
||||||
|
/// </summary>
|
||||||
|
public delegate IClientAPI GetClientDelegate(LLUUID agentID);
|
||||||
|
|
||||||
public class Caps
|
public class Caps
|
||||||
{
|
{
|
||||||
private static readonly log4net.ILog m_log =
|
private static readonly log4net.ILog m_log =
|
||||||
|
@ -99,8 +106,8 @@ namespace OpenSim.Region.Capabilities
|
||||||
public NewInventoryItem AddNewInventoryItem = null;
|
public NewInventoryItem AddNewInventoryItem = null;
|
||||||
public ItemUpdatedCallback ItemUpdatedCall = null;
|
public ItemUpdatedCallback ItemUpdatedCall = null;
|
||||||
public TaskScriptUpdatedCallback TaskScriptUpdatedCall = null;
|
public TaskScriptUpdatedCallback TaskScriptUpdatedCall = null;
|
||||||
//
|
|
||||||
public FetchInventoryDescendentsCAPS CAPSFetchInventoryDescendents = null;
|
public FetchInventoryDescendentsCAPS CAPSFetchInventoryDescendents = null;
|
||||||
|
public GetClientDelegate GetClient = null;
|
||||||
|
|
||||||
public Caps(AssetCache assetCache, BaseHttpServer httpServer, string httpListen, uint httpPort, string capsPath,
|
public Caps(AssetCache assetCache, BaseHttpServer httpServer, string httpListen, uint httpPort, string capsPath,
|
||||||
LLUUID agent, bool dumpAssetsToFile)
|
LLUUID agent, bool dumpAssetsToFile)
|
||||||
|
@ -240,7 +247,7 @@ namespace OpenSim.Region.Capabilities
|
||||||
|
|
||||||
LLSDFetchInventoryDescendents llsdRequest = new LLSDFetchInventoryDescendents();
|
LLSDFetchInventoryDescendents llsdRequest = new LLSDFetchInventoryDescendents();
|
||||||
LLSDHelpers.DeserialiseLLSDMap(inventoryhash, llsdRequest);
|
LLSDHelpers.DeserialiseLLSDMap(inventoryhash, llsdRequest);
|
||||||
LLSDInventoryDescendents reply = FetchInventory(llsdRequest);
|
LLSDInventoryDescendents reply = FetchInventoryReply(llsdRequest);
|
||||||
|
|
||||||
inventoryitemstr = LLSDHelpers.SerialiseLLSDReply(reply);
|
inventoryitemstr = LLSDHelpers.SerialiseLLSDReply(reply);
|
||||||
inventoryitemstr = inventoryitemstr.Replace("<llsd><map><key>folders</key><array>", "");
|
inventoryitemstr = inventoryitemstr.Replace("<llsd><map><key>folders</key><array>", "");
|
||||||
|
@ -265,7 +272,7 @@ namespace OpenSim.Region.Capabilities
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
private LLSDInventoryDescendents FetchInventory(LLSDFetchInventoryDescendents invFetch)
|
private LLSDInventoryDescendents FetchInventoryReply(LLSDFetchInventoryDescendents invFetch)
|
||||||
{
|
{
|
||||||
LLSDInventoryDescendents reply = new LLSDInventoryDescendents();
|
LLSDInventoryDescendents reply = new LLSDInventoryDescendents();
|
||||||
LLSDInventoryFolderContents contents = new LLSDInventoryFolderContents();
|
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);
|
itemList = CAPSFetchInventoryDescendents(m_agentID, invFetch.folder_id, invFetch.owner_id, invFetch.fetch_folders, invFetch.fetch_items, invFetch.sort_order);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (itemList != null)
|
if (itemList != null)
|
||||||
{
|
{
|
||||||
foreach (InventoryItemBase invItem in itemList)
|
foreach (InventoryItemBase invItem in itemList)
|
||||||
|
@ -296,6 +304,27 @@ namespace OpenSim.Region.Capabilities
|
||||||
contents.items.Array.Add(ConvertInventoryItem(invItem));
|
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;
|
contents.descendents = contents.items.Array.Count;
|
||||||
return reply;
|
return reply;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1576,7 +1576,8 @@ namespace OpenSim.Region.ClientStack
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
/// 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.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="message"></param>
|
/// <param name="message"></param>
|
||||||
public void SendAlertMessage(string message)
|
public void SendAlertMessage(string message)
|
||||||
|
@ -1587,10 +1588,12 @@ namespace OpenSim.Region.ClientStack
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
/// Send an agent alert message to the client.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="message"></param>
|
/// <param name="message"></param>
|
||||||
/// <param name="modal"></param>
|
/// <param name="modal">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).</param>
|
||||||
public void SendAgentAlertMessage(string message, bool modal)
|
public void SendAgentAlertMessage(string message, bool modal)
|
||||||
{
|
{
|
||||||
AgentAlertMessagePacket alertPack = (AgentAlertMessagePacket)PacketPool.Instance.GetPacket(PacketType.AgentAlertMessage);
|
AgentAlertMessagePacket alertPack = (AgentAlertMessagePacket)PacketPool.Instance.GetPacket(PacketType.AgentAlertMessage);
|
||||||
|
|
|
@ -619,6 +619,28 @@ namespace OpenSim.Region.Environment.Scenes
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 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).
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="agentId"></param>
|
||||||
|
/// <returns>null if either the avatar wasn't in the scene, or they do not have a controlling client</returns>
|
||||||
|
public IClientAPI GetControllingClient(LLUUID agentId)
|
||||||
|
{
|
||||||
|
ScenePresence presence = GetScenePresence(agentId);
|
||||||
|
|
||||||
|
if (presence != null)
|
||||||
|
{
|
||||||
|
return presence.ControllingClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Request a filtered list of m_scenePresences in this World
|
/// Request a filtered list of m_scenePresences in this World
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -640,16 +662,17 @@ namespace OpenSim.Region.Environment.Scenes
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Request a Avatar by UUID
|
/// Request a scene presence by UUID
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="avatarID"></param>
|
/// <param name="avatarID"></param>
|
||||||
/// <returns></returns>
|
/// <returns>null if the agent was not found</returns>
|
||||||
public ScenePresence GetScenePresence(LLUUID avatarID)
|
public ScenePresence GetScenePresence(LLUUID agentID)
|
||||||
{
|
{
|
||||||
if (ScenePresences.ContainsKey(avatarID))
|
if (ScenePresences.ContainsKey(agentID))
|
||||||
{
|
{
|
||||||
return ScenePresences[avatarID];
|
return ScenePresences[agentID];
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1884,7 +1884,7 @@ namespace OpenSim.Region.Environment.Scenes
|
||||||
cap.ItemUpdatedCall = CapsUpdateInventoryItemAsset;
|
cap.ItemUpdatedCall = CapsUpdateInventoryItemAsset;
|
||||||
cap.TaskScriptUpdatedCall = CapsUpdateTaskInventoryScriptAsset;
|
cap.TaskScriptUpdatedCall = CapsUpdateTaskInventoryScriptAsset;
|
||||||
cap.CAPSFetchInventoryDescendents = CommsManager.UserProfileCacheService.HandleFetchInventoryDescendentsCAPS;
|
cap.CAPSFetchInventoryDescendents = CommsManager.UserProfileCacheService.HandleFetchInventoryDescendentsCAPS;
|
||||||
|
cap.GetClient = m_innerScene.GetControllingClient;
|
||||||
m_capsHandlers[agentId] = cap;
|
m_capsHandlers[agentId] = cap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue