diff --git a/OpenSim/Framework/FriendRegionInfo.cs b/OpenSim/Framework/FriendRegionInfo.cs index ee308ea057..7315bc57da 100644 --- a/OpenSim/Framework/FriendRegionInfo.cs +++ b/OpenSim/Framework/FriendRegionInfo.cs @@ -25,11 +25,14 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +using OpenMetaverse; + namespace OpenSim.Framework { public class FriendRegionInfo { public bool isOnline; public ulong regionHandle; + public UUID regionID; } } diff --git a/OpenSim/Region/Communications/OGS1/OGS1UserServices.cs b/OpenSim/Region/Communications/OGS1/OGS1UserServices.cs index f1e2f042ec..5f39d8f104 100644 --- a/OpenSim/Region/Communications/OGS1/OGS1UserServices.cs +++ b/OpenSim/Region/Communications/OGS1/OGS1UserServices.cs @@ -770,7 +770,15 @@ namespace OpenSim.Region.Communications.OGS1 { FriendRegionInfo info = new FriendRegionInfo(); info.isOnline = (bool)respData["isOnline_" + i]; - if (info.isOnline) info.regionHandle = Convert.ToUInt64(respData["regionHandle_" + i]); + if (info.isOnline) + { + // TODO remove this after the next protocol update (say, r7800?) + info.regionHandle = Convert.ToUInt64(respData["regionHandle_" + i]); + + // accept missing id + if(respData.ContainsKey("regionID_" + i)) + UUID.TryParse((string)respData["regionID_" + i], out info.regionID); + } result.Add(uuid, info); } diff --git a/OpenSim/Region/Environment/Modules/Avatar/InstantMessage/PresenceModule.cs b/OpenSim/Region/Environment/Modules/Avatar/InstantMessage/PresenceModule.cs index 28ed9914c6..4ec80e5919 100644 --- a/OpenSim/Region/Environment/Modules/Avatar/InstantMessage/PresenceModule.cs +++ b/OpenSim/Region/Environment/Modules/Avatar/InstantMessage/PresenceModule.cs @@ -48,6 +48,10 @@ namespace OpenSim.Region.Environment.Modules.Avatar.InstantMessage private bool m_Enabled = false; private bool m_Gridmode = false; + + // some default scene for doing things that aren't connected to a specific scene. Avoids locking. + private Scene m_initialScene; + private List m_Scenes = new List(); private Dictionary m_RootAgents = @@ -75,6 +79,8 @@ namespace OpenSim.Region.Environment.Modules.Avatar.InstantMessage m_Gridmode = cnf.GetBoolean("gridmode", false); m_Enabled = true; + + m_initialScene = scene; } if (m_Gridmode) @@ -84,6 +90,7 @@ namespace OpenSim.Region.Environment.Modules.Avatar.InstantMessage scene.EventManager.OnNewClient += OnNewClient; scene.EventManager.OnSetRootAgentScene += OnSetRootAgentScene; + //scene.EventManager.OnMakeChildAgent += OnMakeChildAgent; m_Scenes.Add(scene); } @@ -98,8 +105,11 @@ namespace OpenSim.Region.Environment.Modules.Avatar.InstantMessage if (!m_Gridmode || !m_Enabled) return; - foreach (Scene scene in m_Scenes) - NotifyMessageServerOfShutdown(scene); + lock (m_Scenes) + { + foreach (Scene scene in m_Scenes) + NotifyMessageServerOfShutdown(scene); + } } public string Name @@ -114,6 +124,58 @@ namespace OpenSim.Region.Environment.Modules.Avatar.InstantMessage public void RequestBulkPresenceData(UUID[] users) { + if (OnBulkPresenceData != null) + { + PresenceInfo[] result = new PresenceInfo[users.Length]; + if (m_Gridmode) + { + // TODO process local info first and only do a server lookup if necessary. + // TODO fix m_RootAgents contents. Currently, they won't work right in a + // non standalone server. Consider two servers, with one sim each in a + // 2x1 grid. Clients will never be closed, just the root moves from + // server to server. But it stays in m_RootAgents on both servers. + Dictionary infos = m_initialScene.GetFriendRegionInfos(new List(users)); + for (int i = 0; i < users.Length; ++i) + { + FriendRegionInfo info; + if (infos.TryGetValue(users[i], out info) && info.isOnline) + { + UUID regionID = info.regionID; + if (regionID == UUID.Zero) + { + // TODO this is the old messaging-server protocol; only the regionHandle is available. + // Fetch region-info to get the id + RegionInfo regionInfo = m_initialScene.RequestNeighbouringRegionInfo(info.regionHandle); + regionID = regionInfo.RegionID; + } + result[i] = new PresenceInfo(users[i], regionID); + } + else result[i] = new PresenceInfo(users[i], UUID.Zero); + } + } + else + { + // in standalone mode, we have all the info locally available. + lock (m_RootAgents) + { + for (int i = 0; i < users.Length; ++i) + { + Scene scene; + if (m_RootAgents.TryGetValue(users[i], out scene)) + { + result[i] = new PresenceInfo(users[i], scene.RegionInfo.RegionID); + } + else + { + result[i] = new PresenceInfo(users[i], UUID.Zero); + } + } + } + } + + // tell everyone + OnBulkPresenceData(result); + } } public void OnNewClient(IClientAPI client) @@ -160,6 +222,25 @@ namespace OpenSim.Region.Environment.Modules.Avatar.InstantMessage NotifyMessageServerOfAgentLocation(agentID, scene.RegionInfo.RegionID, scene.RegionInfo.RegionHandle); } +// TODO not sure about that yet +// public void OnMakeChildAgent(ScenePresence agent) +// { +// // OnMakeChildAgent can be called from several threads at once (with different agent). +// // Concurrent access to m_RootAgents is prone to failure on multi-core/-processor systems without +// // correct locking). +// lock (m_RootAgents) +// { +// Scene rootScene; +// if (m_RootAgents.TryGetValue(agentID, out rootScene) && agent.Scene == rootScene) +// { +// m_RootAgents[agentID] = scene; +// } +// } +// // don't notify the messaging-server; either this is just downgraded and another one will be upgraded +// // to root momentarily (which will notify the messaging-server), or possibly it will be closed in a moment, +// // which will update the messaging-server, too. +// } + private void NotifyMessageServerOfStartup(Scene scene) { Hashtable xmlrpcdata = new Hashtable(); diff --git a/OpenSim/Region/Interfaces/IPresenceModule.cs b/OpenSim/Region/Interfaces/IPresenceModule.cs index 2023f25d18..23cf064cfc 100644 --- a/OpenSim/Region/Interfaces/IPresenceModule.cs +++ b/OpenSim/Region/Interfaces/IPresenceModule.cs @@ -35,6 +35,12 @@ namespace OpenSim.Region.Interfaces { public UUID userID; public UUID regionID; + + public PresenceInfo(UUID userID, UUID regionID) + { + this.userID = userID; + this.regionID = regionID; + } } public delegate void PresenceChange(PresenceInfo info);