Merge branch 'master' into bigmerge

Conflicts:
	OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
This commit is contained in:
Melanie
2011-11-17 19:04:27 +00:00
30 changed files with 375 additions and 595 deletions

View File

@@ -29,6 +29,7 @@ using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Threading;
using log4net;
using Nini.Config;
using Nwc.XmlRpc;
@@ -79,10 +80,20 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
protected IFriendsService m_FriendsService = null;
protected FriendsSimConnector m_FriendsSimConnector;
protected Dictionary<UUID, UserFriendData> m_Friends =
new Dictionary<UUID, UserFriendData>();
/// <summary>
/// Cache friends lists for users.
/// </summary>
/// <remarks>
/// This is a complex and error-prone thing to do. At the moment, we assume that the efficiency gained in
/// permissions checks outweighs the disadvantages of that complexity.
/// </remarks>
protected Dictionary<UUID, UserFriendData> m_Friends = new Dictionary<UUID, UserFriendData>();
protected HashSet<UUID> m_NeedsListOfFriends = new HashSet<UUID>();
/// <summary>
/// Maintain a record of viewers that need to be sent notifications for friends that are online. This only
/// needs to be done on login. Subsequent online/offline friend changes are sent by a different mechanism.
/// </summary>
protected HashSet<UUID> m_NeedsListOfOnlineFriends = new HashSet<UUID>();
protected IPresenceService PresenceService
{
@@ -189,6 +200,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
{
if (!m_Enabled)
return;
m_log.DebugFormat("[FRIENDS MODULE]: AddRegion on {0}", Name);
m_Scenes.Add(scene);
@@ -241,16 +253,25 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
client.OnInstantMessage += OnInstantMessage;
client.OnApproveFriendRequest += OnApproveFriendRequest;
client.OnDenyFriendRequest += OnDenyFriendRequest;
client.OnTerminateFriendship += OnTerminateFriendship;
client.OnTerminateFriendship += (thisClient, agentID, exfriendID) => RemoveFriendship(thisClient, exfriendID);
client.OnGrantUserRights += OnGrantUserRights;
Util.FireAndForget(delegate { FetchFriendslist(client); });
// Do not do this asynchronously. If we do, then subsequent code can outrace CacheFriends() and
// return misleading results from the still empty friends cache.
// If we absolutely need to do this asynchronously, then a signalling mechanism is needed so that calls
// to GetFriends() will wait until CacheFriends() completes. Locks are insufficient.
CacheFriends(client);
}
/// Fetch the friends list or increment the refcount for the existing
/// friends list
/// <summary>
/// Cache the friends list or increment the refcount for the existing friends list.
/// </summary>
/// <param name="client">
/// </param>
/// <returns>
/// Returns true if the list was fetched, false if it wasn't
protected virtual bool FetchFriendslist(IClientAPI client)
/// </returns>
protected virtual bool CacheFriends(IClientAPI client)
{
UUID agentID = client.AgentId;
lock (m_Friends)
@@ -297,7 +318,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
private void OnMakeRootAgent(ScenePresence sp)
{
RefetchFriends(sp.ControllingClient);
RecacheFriends(sp.ControllingClient);
}
private void OnClientLogin(IClientAPI client)
@@ -309,8 +330,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
StatusChange(agentID, true);
// Register that we need to send the list of online friends to this user
lock (m_NeedsListOfFriends)
m_NeedsListOfFriends.Add(agentID);
lock (m_NeedsListOfOnlineFriends)
m_NeedsListOfOnlineFriends.Add(agentID);
}
public virtual bool SendFriendsOnlineIfNeeded(IClientAPI client)
@@ -318,9 +339,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
UUID agentID = client.AgentId;
// Check if the online friends list is needed
lock (m_NeedsListOfFriends)
lock (m_NeedsListOfOnlineFriends)
{
if (!m_NeedsListOfFriends.Remove(agentID))
if (!m_NeedsListOfOnlineFriends.Remove(agentID))
return false;
}
@@ -328,7 +349,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
List<UUID> online = GetOnlineFriends(agentID);
if (online.Count > 0)
{
m_log.DebugFormat("[FRIENDS MODULE]: User {0} in region {1} has {2} friends online", client.AgentId, client.Scene.RegionInfo.RegionName, online.Count);
m_log.DebugFormat(
"[FRIENDS MODULE]: User {0} in region {1} has {2} friends online",
client.Name, client.Scene.RegionInfo.RegionName, online.Count);
client.SendAgentOnline(online.ToArray());
}
@@ -586,7 +610,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
}
// Update the local cache
RefetchFriends(client);
RecacheFriends(client);
//
// Notify the friend
@@ -641,14 +665,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
}
}
}
private void OnTerminateFriendship(IClientAPI client, UUID agentID, UUID exfriendID)
public void RemoveFriendship(IClientAPI client, UUID exfriendID)
{
if (!DeleteFriendship(agentID, exfriendID))
if (!DeleteFriendship(client.AgentId, exfriendID))
client.SendAlertMessage("Unable to terminate friendship on this sim.");
// Update local cache
RefetchFriends(client);
RecacheFriends(client);
client.SendTerminateFriend(exfriendID);
@@ -667,9 +691,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
if (friendSession != null)
{
GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID);
m_FriendsSimConnector.FriendshipTerminated(region, agentID, exfriendID);
m_FriendsSimConnector.FriendshipTerminated(region, client.AgentId, exfriendID);
}
}
}
}
private void OnGrantUserRights(IClientAPI remoteClient, UUID requester, UUID target, int rights)
@@ -769,7 +793,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
// Update the local cache
RefetchFriends(friendClient);
RecacheFriends(friendClient);
// we're done
return true;
@@ -802,7 +826,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
// the friend in this sim as root agent
friendClient.SendTerminateFriend(exfriendID);
// update local cache
RefetchFriends(friendClient);
RecacheFriends(friendClient);
// we're done
return true;
}
@@ -819,16 +843,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
if (onlineBitChanged)
{
if ((rights & (int)FriendRights.CanSeeOnline) == 1)
friendClient.SendAgentOnline(new UUID[] { new UUID(userID) });
friendClient.SendAgentOnline(new UUID[] { userID });
else
friendClient.SendAgentOffline(new UUID[] { new UUID(userID) });
friendClient.SendAgentOffline(new UUID[] { userID });
}
else
{
bool canEditObjectsChanged = ((rights ^ userFlags) & (int)FriendRights.CanModifyObjects) != 0;
if (canEditObjectsChanged)
friendClient.SendChangeUserRights(userID, friendID, rights);
}
// Update local cache
@@ -847,7 +870,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
IClientAPI friendClient = LocateClientObject(friendID);
if (friendClient != null)
{
// the friend in this sim as root agent
// the friend in this sim as root agent
if (online)
friendClient.SendAgentOnline(new UUID[] { userID });
else
@@ -902,8 +925,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
return FriendsService.GetFriends(client.AgentId);
}
private void RefetchFriends(IClientAPI client)
private void RecacheFriends(IClientAPI client)
{
// FIXME: Ideally, we want to avoid doing this here since it sits the EventManager.OnMakeRootAgent event
// is on the critical path for transferring an avatar from one region to another.
UUID agentID = client.AgentId;
lock (m_Friends)
{

View File

@@ -30,7 +30,6 @@ using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Threading;
using log4net;
using Nini.Config;
using Nwc.XmlRpc;
@@ -84,9 +83,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
#endregion
protected override bool FetchFriendslist(IClientAPI client)
protected override bool CacheFriends(IClientAPI client)
{
if (base.FetchFriendslist(client))
// m_log.DebugFormat("[HGFRIENDS MODULE]: Entered CacheFriends for {0}", client.Name);
if (base.CacheFriends(client))
{
UUID agentID = client.AgentId;
// we do this only for the root agent
@@ -110,14 +111,20 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
}
}
}
// m_log.DebugFormat("[HGFRIENDS MODULE]: Exiting CacheFriends for {0} since detected root agent", client.Name);
return true;
}
}
// m_log.DebugFormat("[HGFRIENDS MODULE]: Exiting CacheFriends for {0} since detected not root agent", client.Name);
return false;
}
public override bool SendFriendsOnlineIfNeeded(IClientAPI client)
{
// m_log.DebugFormat("[HGFRIENDS MODULE]: Entering SendFriendsOnlineIfNeeded for {0}", client.Name);
if (base.SendFriendsOnlineIfNeeded(client))
{
AgentCircuitData aCircuit = ((Scene)client.Scene).AuthenticateHandler.GetAgentCircuitData(client.AgentId);
@@ -134,11 +141,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
}
}
}
// m_log.DebugFormat("[HGFRIENDS MODULE]: Exiting SendFriendsOnlineIfNeeded for {0}", client.Name);
return false;
}
protected override void GetOnlineFriends(UUID userID, List<string> friendList, /*collector*/ List<UUID> online)
{
// m_log.DebugFormat("[HGFRIENDS MODULE]: Entering GetOnlineFriends for {0}", userID);
List<string> fList = new List<string>();
foreach (string s in friendList)
{
@@ -157,6 +168,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
if (UUID.TryParse(pi.UserID, out presenceID))
online.Add(presenceID);
}
// m_log.DebugFormat("[HGFRIENDS MODULE]: Exiting GetOnlineFriends for {0}", userID);
}
//protected override void GetOnlineFriends(UUID userID, List<string> friendList, /*collector*/ List<UUID> online)
@@ -246,6 +259,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
protected override void StatusNotify(List<FriendInfo> friendList, UUID userID, bool online)
{
// m_log.DebugFormat("[HGFRIENDS MODULE]: Entering StatusNotify for {0}", userID);
// First, let's divide the friends on a per-domain basis
Dictionary<string, List<FriendInfo>> friendsPerDomain = new Dictionary<string, List<FriendInfo>>();
foreach (FriendInfo friend in friendList)
@@ -298,6 +313,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
}
}
}
// m_log.DebugFormat("[HGFRIENDS MODULE]: Exiting StatusNotify for {0}", userID);
}
protected override bool GetAgentInfo(UUID scopeID, string fid, out UUID agentID, out string first, out string last)
@@ -351,6 +368,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
protected override FriendInfo[] GetFriendsFromService(IClientAPI client)
{
// m_log.DebugFormat("[HGFRIENDS MODULE]: Entering GetFriendsFromService for {0}", client.Name);
UserAccount account1 = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, client.AgentId);
if (account1 != null)
return base.GetFriendsFromService(client);
@@ -365,6 +384,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
finfos = FriendsService.GetFriends(agentUUI);
m_log.DebugFormat("[HGFRIENDS MODULE]: Fetched {0} local friends for visitor {1}", finfos.Length, agentUUI);
}
// m_log.DebugFormat("[HGFRIENDS MODULE]: Exiting GetFriendsFromService for {0}", client.Name);
return finfos;
}
@@ -401,7 +423,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
}
return false;
}
protected override void StoreBackwards(UUID friendID, UUID agentID)
@@ -627,4 +648,4 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
}
}
}
}
}

View File

@@ -71,12 +71,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends.Tests
ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId);
Assert.That(((TestClient)sp.ControllingClient).OfflineNotificationsReceived.Count, Is.EqualTo(0));
Assert.That(((TestClient)sp.ControllingClient).OnlineNotificationsReceived.Count, Is.EqualTo(0));
Assert.That(((TestClient)sp.ControllingClient).ReceivedOfflineNotifications.Count, Is.EqualTo(0));
Assert.That(((TestClient)sp.ControllingClient).ReceivedOnlineNotifications.Count, Is.EqualTo(0));
}
[Test]
public void TestAddFriendWhileOnline()
public void TestAddFriendshipWhileOnline()
{
TestHelpers.InMethod();
// log4net.Config.XmlConfigurator.Configure();
@@ -91,8 +91,28 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends.Tests
// notification.
m_fm.AddFriendship(sp.ControllingClient, user2Id);
Assert.That(((TestClient)sp.ControllingClient).OfflineNotificationsReceived.Count, Is.EqualTo(0));
Assert.That(((TestClient)sp.ControllingClient).OnlineNotificationsReceived.Count, Is.EqualTo(1));
Assert.That(((TestClient)sp.ControllingClient).ReceivedOfflineNotifications.Count, Is.EqualTo(0));
Assert.That(((TestClient)sp.ControllingClient).ReceivedOnlineNotifications.Count, Is.EqualTo(1));
}
[Test]
public void TestRemoveFriendshipWhileOnline()
{
TestHelpers.InMethod();
// log4net.Config.XmlConfigurator.Configure();
UUID user1Id = TestHelpers.ParseTail(0x1);
UUID user2Id = TestHelpers.ParseTail(0x2);
ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, user1Id);
SceneHelpers.AddScenePresence(m_scene, user2Id);
m_fm.AddFriendship(sp.ControllingClient, user2Id);
m_fm.RemoveFriendship(sp.ControllingClient, user2Id);
TestClient user1Client = sp.ControllingClient as TestClient;
Assert.That(user1Client.ReceivedFriendshipTerminations.Count, Is.EqualTo(1));
Assert.That(user1Client.ReceivedFriendshipTerminations[0], Is.EqualTo(user2Id));
}
}
}

View File

@@ -31,7 +31,6 @@ using System.Reflection;
using OpenSim.Framework;
using OpenSim.Framework.Console;
using OpenSim.Region.Framework;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
@@ -44,13 +43,13 @@ using Nini.Config;
namespace OpenSim.Region.CoreModules.Framework.UserManagement
{
struct UserData
class UserData
{
public UUID Id;
public string FirstName;
public string LastName;
public string HomeURL;
public Dictionary<string, object> ServerURLs;
public UUID Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string HomeURL { get; set; }
public Dictionary<string, object> ServerURLs { get; set; }
}
public class UserManagementModule : ISharedRegionModule, IUserManagement
@@ -130,7 +129,9 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
public void Close()
{
m_Scenes.Clear();
m_UserCache.Clear();
lock (m_UserCache)
m_UserCache.Clear();
}
#endregion ISharedRegionModule
@@ -188,11 +189,14 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
{
string[] returnstring = new string[2];
if (m_UserCache.ContainsKey(uuid))
lock (m_UserCache)
{
returnstring[0] = m_UserCache[uuid].FirstName;
returnstring[1] = m_UserCache[uuid].LastName;
return returnstring;
if (m_UserCache.ContainsKey(uuid))
{
returnstring[0] = m_UserCache[uuid].FirstName;
returnstring[1] = m_UserCache[uuid].LastName;
return returnstring;
}
}
UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(UUID.Zero, uuid);
@@ -237,22 +241,36 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
public string GetUserHomeURL(UUID userID)
{
if (m_UserCache.ContainsKey(userID))
return m_UserCache[userID].HomeURL;
lock (m_UserCache)
{
if (m_UserCache.ContainsKey(userID))
return m_UserCache[userID].HomeURL;
}
return string.Empty;
}
public string GetUserServerURL(UUID userID, string serverType)
{
if (m_UserCache.ContainsKey(userID))
{
UserData userdata = m_UserCache[userID];
if (userdata.ServerURLs != null && userdata.ServerURLs.ContainsKey(serverType) && userdata.ServerURLs[serverType] != null)
return userdata.ServerURLs[serverType].ToString();
UserData userdata;
lock (m_UserCache)
m_UserCache.TryGetValue(userID, out userdata);
if (userdata.HomeURL != string.Empty)
if (userdata != null)
{
// m_log.DebugFormat("[USER MANAGEMENT MODULE]: Requested url type {0} for {1}", serverType, userID);
if (userdata.ServerURLs != null && userdata.ServerURLs.ContainsKey(serverType) && userdata.ServerURLs[serverType] != null)
{
return userdata.ServerURLs[serverType].ToString();
}
if (userdata.HomeURL != null && userdata.HomeURL != string.Empty)
{
m_log.DebugFormat(
"[USER MANAGEMENT MODULE]: Did not find url type {0} so requesting urls from '{1}' for {2}",
serverType, userdata.HomeURL, userID);
UserAgentServiceConnector uConn = new UserAgentServiceConnector(userdata.HomeURL);
userdata.ServerURLs = uConn.GetServerURLs(userID);
if (userdata.ServerURLs != null && userdata.ServerURLs.ContainsKey(serverType) && userdata.ServerURLs[serverType] != null)
@@ -269,9 +287,12 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
if (account != null)
return userID.ToString();
if (m_UserCache.ContainsKey(userID))
UserData ud;
lock (m_UserCache)
m_UserCache.TryGetValue(userID, out ud);
if (ud != null)
{
UserData ud = m_UserCache[userID];
string homeURL = ud.HomeURL;
string first = ud.FirstName, last = ud.LastName;
if (ud.LastName.StartsWith("@"))
@@ -291,8 +312,11 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
public void AddUser(UUID uuid, string first, string last)
{
if (m_UserCache.ContainsKey(uuid))
return;
lock (m_UserCache)
{
if (m_UserCache.ContainsKey(uuid))
return;
}
UserData user = new UserData();
user.Id = uuid;
@@ -310,8 +334,11 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
public void AddUser(UUID id, string creatorData)
{
if (m_UserCache.ContainsKey(id))
return;
lock (m_UserCache)
{
if (m_UserCache.ContainsKey(id))
return;
}
// m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, craetorData {1}", id, creatorData);
@@ -402,22 +429,24 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
private void HandleShowUsers(string module, string[] cmd)
{
if (m_UserCache.Count == 0)
lock (m_UserCache)
{
MainConsole.Instance.Output("No users not found");
if (m_UserCache.Count == 0)
{
MainConsole.Instance.Output("No users not found");
return;
}
MainConsole.Instance.Output("UUID User Name");
MainConsole.Instance.Output("-----------------------------------------------------------------------------");
foreach (KeyValuePair<UUID, UserData> kvp in m_UserCache)
{
MainConsole.Instance.Output(String.Format("{0} {1} {2}",
kvp.Key, kvp.Value.FirstName, kvp.Value.LastName));
}
return;
}
MainConsole.Instance.Output("UUID User Name");
MainConsole.Instance.Output("-----------------------------------------------------------------------------");
foreach (KeyValuePair<UUID, UserData> kvp in m_UserCache)
{
MainConsole.Instance.Output(String.Format("{0} {1} {2}",
kvp.Key, kvp.Value.FirstName, kvp.Value.LastName));
}
return;
}
}
}
}

View File

@@ -479,8 +479,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
}
protected bool IsFriendWithPerms(UUID user,UUID objectOwner)
{
{
if (user == UUID.Zero)
return false;

View File

@@ -65,7 +65,6 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
private OpenSim.Framework.BlockingQueue<MapRequestState> requests = new OpenSim.Framework.BlockingQueue<MapRequestState>();
//private IConfig m_config;
protected Scene m_scene;
private List<MapBlockData> cachedMapBlocks = new List<MapBlockData>();
private int cachedTime = 0;
@@ -348,7 +347,11 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
// m_log.Debug("[WORLD MAP]: Starting remote MapItem request thread");
Watchdog.StartThread(process, "MapItemRequestThread", ThreadPriority.BelowNormal, true);
Watchdog.StartThread(
process,
string.Format("MapItemRequestThread ({0})", m_scene.RegionInfo.RegionName),
ThreadPriority.BelowNormal,
true);
}
/// <summary>
@@ -357,7 +360,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
private void StopThread()
{
MapRequestState st = new MapRequestState();
st.agentID=STOP_UUID;
st.agentID = STOP_UUID;
st.EstateID=0;
st.flags=0;
st.godlike=false;