diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
index 4f8e2cdbfc..40a400f957 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
@@ -428,7 +428,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
///
/// delegate for sending a grid instant message asynchronously
///
- public delegate void GridInstantMessageDelegate(GridInstantMessage im, MessageResultNotification result);
+ public delegate void GridInstantMessageDelegate(GridInstantMessage im, MessageResultNotification result, UUID prevRegionID);
protected virtual void GridInstantMessageCompleted(IAsyncResult iar)
{
@@ -442,118 +442,138 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
{
GridInstantMessageDelegate d = SendGridInstantMessageViaXMLRPCAsync;
- d.BeginInvoke(im, result, GridInstantMessageCompleted, d);
+ d.BeginInvoke(im, result, UUID.Zero, GridInstantMessageCompleted, d);
}
///
- /// Internal SendGridInstantMessage over XMLRPC method.
+ /// Recursive SendGridInstantMessage over XMLRPC method.
/// This is called from within a dedicated thread.
+ /// The first time this is called, prevRegionHandle will be 0 Subsequent times this is called from
+ /// itself, prevRegionHandle will be the last region handle that we tried to send.
+ /// If the handles are the same, we look up the user's location using the grid.
+ /// If the handles are still the same, we end. The send failed.
///
- private void SendGridInstantMessageViaXMLRPCAsync(GridInstantMessage im, MessageResultNotification result)
+ ///
+ /// Pass in 0 the first time this method is called. It will be called recursively with the last
+ /// regionhandle tried
+ ///
+ protected virtual void SendGridInstantMessageViaXMLRPCAsync(GridInstantMessage im, MessageResultNotification result, UUID prevRegionID)
{
UUID toAgentID = new UUID(im.toAgentID);
- UUID regionID;
- bool lookupAgent;
- /*
- * Try to get what region the agent is in from the cache.
- */
+ PresenceInfo upd = null;
+
+ bool lookupAgent = false;
+
lock (m_UserRegionMap)
{
- lookupAgent = !m_UserRegionMap.TryGetValue(toAgentID, out regionID);
- }
-
- while (true)
- {
-
- /*
- * If not in cache, try to find out what region the agent is in.
- * Also do this if we know the existing cache entry is bad.
- */
- if (lookupAgent)
+ if (m_UserRegionMap.ContainsKey(toAgentID))
{
- PresenceInfo[] presences = PresenceService.GetAgents(new string[] { toAgentID.ToString() });
+ upd = new PresenceInfo();
+ upd.RegionID = m_UserRegionMap[toAgentID];
- regionID = UUID.Zero;
- if (presences != null)
+ // We need to compare the current regionhandle with the previous region handle
+ // or the recursive loop will never end because it will never try to lookup the agent again
+ if (prevRegionID == upd.RegionID)
{
- foreach (PresenceInfo p in presences)
+ lookupAgent = true;
+ }
+ }
+ else
+ {
+ lookupAgent = true;
+ }
+ }
+
+
+ // Are we needing to look-up an agent?
+ if (lookupAgent)
+ {
+ // Non-cached user agent lookup.
+ PresenceInfo[] presences = PresenceService.GetAgents(new string[] { toAgentID.ToString() });
+ if (presences != null && presences.Length > 0)
+ {
+ foreach (PresenceInfo p in presences)
+ {
+ if (p.RegionID != UUID.Zero)
{
- if (p.RegionID != UUID.Zero)
- {
- regionID = p.RegionID;
- break;
- }
+ upd = p;
+ break;
}
}
-
- // If not found, message is undeliverable
- if (regionID == UUID.Zero)
- {
- break;
- }
}
- /*
- * Try to find out about region.
- * If unable, message is undeliverable.
- */
- GridRegion reginfo = m_Scenes[0].GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, regionID);
- if (reginfo == null)
+ if (upd != null)
{
- m_log.WarnFormat("[GRID INSTANT MESSAGE]: Unable to find region {0}", regionID);
- break;
- }
-
- /*
- * Try to send message to agent in the region.
- */
- Hashtable msgdata = ConvertGridInstantMessageToXMLRPC(im);
- msgdata["region_handle"] = 0;
- bool imresult = doIMSending(reginfo, msgdata);
-
- /*
- * If message delivery successful, save cache entry because we know it is good.
- * Then tell caller message has been delivered and we are done.
- */
- if (imresult)
- {
- lock (m_UserRegionMap)
+ // check if we've tried this before..
+ // This is one way to end the recursive loop
+ //
+ if (upd.RegionID == prevRegionID)
{
- m_UserRegionMap[toAgentID] = regionID;
+ // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message");
+ HandleUndeliveredMessage(im, result);
+ return;
}
- result(true);
+ }
+ else
+ {
+ // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message");
+ HandleUndeliveredMessage(im, result);
return;
}
-
- /*
- * Message delivery failed.
- * If we just looked up what region the agent is in, message is undeliverable.
- */
- if (lookupAgent)
- {
- break;
- }
-
- /*
- * We used a cached entry that we now know is bad.
- * Try again by searching the grid for the user.
- */
- lookupAgent = true;
}
- /*
- * Message is undeliverable for one reason or another.
- * Remove possible bad entry from cache.
- * Then inform caller that the message is undeliverable.
- */
- lock (m_UserRegionMap)
+ if (upd != null)
{
- m_UserRegionMap.Remove(toAgentID);
- }
+ GridRegion reginfo = m_Scenes[0].GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID,
+ upd.RegionID);
+ if (reginfo != null)
+ {
+ Hashtable msgdata = ConvertGridInstantMessageToXMLRPC(im);
+ // Not actually used anymore, left in for compatibility
+ // Remove at next interface change
+ //
+ msgdata["region_handle"] = 0;
+ bool imresult = doIMSending(reginfo, msgdata);
+ if (imresult)
+ {
+ // IM delivery successful, so store the Agent's location in our local cache.
+ lock (m_UserRegionMap)
+ {
+ if (m_UserRegionMap.ContainsKey(toAgentID))
+ {
+ m_UserRegionMap[toAgentID] = upd.RegionID;
+ }
+ else
+ {
+ m_UserRegionMap.Add(toAgentID, upd.RegionID);
+ }
+ }
+ result(true);
+ }
+ else
+ {
+ // try again, but lookup user this time.
+ // Warning, this must call the Async version
+ // of this method or we'll be making thousands of threads
+ // The version within the spawned thread is SendGridInstantMessageViaXMLRPCAsync
+ // The version that spawns the thread is SendGridInstantMessageViaXMLRPC
- // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message");
- HandleUndeliveredMessage(im, result);
+ // This is recursive!!!!!
+ SendGridInstantMessageViaXMLRPCAsync(im, result,
+ upd.RegionID);
+ }
+ }
+ else
+ {
+ m_log.WarnFormat("[GRID INSTANT MESSAGE]: Unable to find region {0}", upd.RegionID);
+ HandleUndeliveredMessage(im, result);
+ }
+ }
+ else
+ {
+ HandleUndeliveredMessage(im, result);
+ }
}
///