diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs index 7aa7123144..2462ff837b 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, UUID prevRegionID); + public delegate void GridInstantMessageDelegate(GridInstantMessage im, MessageResultNotification result); protected virtual void GridInstantMessageCompleted(IAsyncResult iar) { @@ -442,138 +442,87 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage { GridInstantMessageDelegate d = SendGridInstantMessageViaXMLRPCAsync; - d.BeginInvoke(im, result, UUID.Zero, GridInstantMessageCompleted, d); + d.BeginInvoke(im, result, GridInstantMessageCompleted, d); } /// - /// 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. + /// Internal SendGridInstantMessage over XMLRPC method. /// - /// - /// 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) + /// + /// This is called from within a dedicated thread. + /// + private void SendGridInstantMessageViaXMLRPCAsync(GridInstantMessage im, MessageResultNotification result) { UUID toAgentID = new UUID(im.toAgentID); - - PresenceInfo upd = null; - - bool lookupAgent = false; + UUID regionID; + bool needToLookupAgent; lock (m_UserRegionMap) - { - if (m_UserRegionMap.ContainsKey(toAgentID)) - { - upd = new PresenceInfo(); - upd.RegionID = m_UserRegionMap[toAgentID]; + needToLookupAgent = !m_UserRegionMap.TryGetValue(toAgentID, out regionID); - // 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) - { - lookupAgent = true; - } - } - else - { - lookupAgent = true; - } - } - - - // Are we needing to look-up an agent? - if (lookupAgent) + while (true) { - // Non-cached user agent lookup. - PresenceInfo[] presences = PresenceService.GetAgents(new string[] { toAgentID.ToString() }); - if (presences != null && presences.Length > 0) + if (needToLookupAgent) { - foreach (PresenceInfo p in presences) + PresenceInfo[] presences = PresenceService.GetAgents(new string[] { toAgentID.ToString() }); + + UUID foundRegionID = UUID.Zero; + + if (presences != null) { - if (p.RegionID != UUID.Zero) + foreach (PresenceInfo p in presences) { - upd = p; - break; + if (p.RegionID != UUID.Zero) + { + foundRegionID = p.RegionID; + break; + } } } + + // If not found or the found region is the same as the last lookup, then message is undeliverable + if (foundRegionID == UUID.Zero || foundRegionID == regionID) + break; + else + regionID = foundRegionID; } - if (upd != null) + GridRegion reginfo = m_Scenes[0].GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, regionID); + if (reginfo == null) { - // check if we've tried this before.. - // This is one way to end the recursive loop - // - if (upd.RegionID == prevRegionID) - { - // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); - HandleUndeliverableMessage(im, result); - return; - } + m_log.WarnFormat("[GRID INSTANT MESSAGE]: Unable to find region {0}", regionID); + break; } - else + + // Try to send the message to the agent via the retrieved region. + Hashtable msgdata = ConvertGridInstantMessageToXMLRPC(im); + msgdata["region_handle"] = 0; + bool imresult = doIMSending(reginfo, msgdata); + + // If the message delivery was successful, then cache the entry. + if (imresult) { - // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); - HandleUndeliverableMessage(im, result); + lock (m_UserRegionMap) + { + m_UserRegionMap[toAgentID] = regionID; + } + result(true); return; } + + // If we reach this point in the first iteration of the while, then we may have unsuccessfully tried + // to use a locally cached region ID. All subsequent attempts need to lookup agent details from + // the presence service. + needToLookupAgent = true; } - if (upd != null) - { - 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 + // If we reached this point then the message was not deliverable. Remove the bad cache entry and + // signal the delivery failure. + lock (m_UserRegionMap) + m_UserRegionMap.Remove(toAgentID); - // This is recursive!!!!! - SendGridInstantMessageViaXMLRPCAsync(im, result, - upd.RegionID); - } - } - else - { - m_log.WarnFormat("[GRID INSTANT MESSAGE]: Unable to find region {0}", upd.RegionID); - HandleUndeliverableMessage(im, result); - } - } - else - { - HandleUndeliverableMessage(im, result); - } + // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); + HandleUndeliverableMessage(im, result); } /// @@ -584,7 +533,6 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage /// Bool if the message was successfully delivered at the other side. protected virtual bool doIMSending(GridRegion reginfo, Hashtable xmlrpcdata) { - ArrayList SendParams = new ArrayList(); SendParams.Add(xmlrpcdata); XmlRpcRequest GridReq = new XmlRpcRequest("grid_instant_message", SendParams);