Bug fix in new child agents management. Thanks DigiDaz for helping identify this issue.

We need to update all child agents whenever the root agent crosses regions. The update
now includes child agents in common neighbours. This is so that those get updated with the
seeds of the new child agents that are spawned from the receiving region.
This also fixes some timing issues. We need to close child agents from the originating region
before we update child agents in the receiving region.
0.6.1-post-fixes
diva 2008-12-15 16:23:34 +00:00
parent 43142afab1
commit 4b71b88114
4 changed files with 174 additions and 116 deletions

View File

@ -169,6 +169,17 @@ namespace OpenSim.Region.Environment.Scenes.Hypergrid
// once we reach here...
//avatar.Scene.RemoveCapsHandler(avatar.UUID);
// Let's close some agents
if (isHyperLink) // close them all except this one
{
List<ulong> regions = new List<ulong>(avatar.KnownChildRegionHandles);
regions.Remove(avatar.Scene.RegionInfo.RegionHandle);
SendCloseChildAgentConnections(avatar.UUID, regions);
}
else // close just a few
avatar.CloseChildAgents(newRegionX, newRegionY);
string capsPath = String.Empty;
AgentCircuitData agent = avatar.ControllingClient.RequestClientInfo();
agent.BaseFolder = UUID.Zero;
agent.InventoryFolder = UUID.Zero;
@ -178,13 +189,6 @@ namespace OpenSim.Region.Environment.Scenes.Hypergrid
{
// brand new agent
agent.CapsPath = Util.GetRandomCapsPath();
}
else
{
// child agent already there
agent.CapsPath = avatar.Scene.GetChildSeed(avatar.UUID, reg.RegionHandle);
}
if (!m_commsProvider.InterRegion.InformRegionOfChildAgent(reg.RegionHandle, agent))
{
avatar.ControllingClient.SendTeleportFailed("Destination is not accepting teleports.");
@ -192,7 +196,7 @@ namespace OpenSim.Region.Environment.Scenes.Hypergrid
}
// TODO Should construct this behind a method
string capsPath =
capsPath =
"http://" + reg.ExternalHostName + ":" + reg.HttpPort
+ "/CAPS/" + agent.CapsPath + "0000/";
@ -209,6 +213,14 @@ namespace OpenSim.Region.Environment.Scenes.Hypergrid
avatar.ControllingClient.InformClientOfNeighbour(realHandle, reg.ExternalEndPoint);
// TODO: make Event Queue disablable!
}
}
else
{
// child agent already there
agent.CapsPath = avatar.Scene.GetChildSeed(avatar.UUID, reg.RegionHandle);
capsPath = "http://" + reg.ExternalHostName + ":" + reg.HttpPort
+ "/CAPS/" + agent.CapsPath + "0000/";
}
m_commsProvider.InterRegion.ExpectAvatarCrossing(reg.RegionHandle, avatar.ControllingClient.AgentId,
position, false);
@ -258,29 +270,25 @@ namespace OpenSim.Region.Environment.Scenes.Hypergrid
}
// Let's close some children agents
if (isHyperLink) // close them all
SendCloseChildAgentConnections(avatar.UUID, avatar.KnownChildRegionHandles);
else // close just a few
avatar.CloseChildAgents(newRegionX, newRegionY);
//avatar.Close();
// Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone
///
/// Hypergrid mod: extra check for isHyperLink
///
//if (Util.IsOutsideView(oldRegionX, newRegionX, oldRegionY, newRegionY))
//{
// CloseConnection(avatar.UUID);
//}
if (Util.IsOutsideView(oldRegionX, newRegionX, oldRegionY, newRegionY) || isHyperLink)
{
CloseConnection(avatar.UUID);
}
// if (teleport success) // seems to be always success here
// the user may change their profile information in other region,
// so the userinfo in UserProfileCache is not reliable any more, delete it
if (avatar.Scene.NeedSceneCacheClear(avatar.UUID))
{
m_commsProvider.UserProfileCacheService.RemoveUser(avatar.UUID);
m_log.InfoFormat("[HGSceneCommService]: User {0} is going to another region, profile cache removed", avatar.UUID);
}
}
else
{
avatar.ControllingClient.SendTeleportFailed("Remote Region appears to be down");

View File

@ -2657,7 +2657,7 @@ namespace OpenSim.Region.Environment.Scenes
GetAvatarAppearance(client, out appearance);
ScenePresence avatar = m_sceneGraph.CreateAndAddChildScenePresence(client, appearance);
avatar.KnownRegions = GetChildrenSeeds(avatar.UUID);
//avatar.KnownRegions = GetChildrenSeeds(avatar.UUID);
return avatar;
}
@ -2871,9 +2871,6 @@ namespace OpenSim.Region.Environment.Scenes
/// <param name="agent"></param>
public void NewUserConnection(AgentCircuitData agent)
{
m_log.DebugFormat("[CONNECTION DEBUGGING] Adding NewUserConnection for {0} in {1} with CC of {2}", agent.AgentID,
RegionInfo.RegionName, agent.circuitcode);
if (m_regInfo.EstateSettings.IsBanned(agent.AgentID))
{
m_log.WarnFormat(
@ -2883,9 +2880,19 @@ namespace OpenSim.Region.Environment.Scenes
/// Diva: Horrible stuff!
capsPaths[agent.AgentID] = agent.CapsPath;
//m_log.DebugFormat("------------>child seeds in {0}: {1}", RegionInfo.RegionName, ((agent.ChildrenCapSeeds == null) ? "null" : agent.ChildrenCapSeeds.Count.ToString()));
childrenSeeds[agent.AgentID] = ((agent.ChildrenCapSeeds == null) ? new Dictionary<ulong, string>() : agent.ChildrenCapSeeds);
ScenePresence sp = m_sceneGraph.GetScenePresence(agent.AgentID);
if (sp != null)
{
m_log.DebugFormat("[CONNECTION DEBUGGING]: Updated agent {0} in {1}", agent.AgentID, RegionInfo.RegionName);
sp.AdjustKnownSeeds();
return;
}
m_log.DebugFormat("[CONNECTION DEBUGGING]: Adding NewUserConnection for {0} in {1} with CC of {2}", agent.AgentID,
RegionInfo.RegionName, agent.circuitcode);
AddCapsHandler(agent.AgentID);
if (!agent.child)

View File

@ -255,7 +255,7 @@ namespace OpenSim.Region.Environment.Scenes
#region Inform Client of Neighbours
private delegate void InformClientOfNeighbourDelegate(
ScenePresence avatar, AgentCircuitData a, SimpleRegionInfo reg, IPEndPoint endPoint);
ScenePresence avatar, AgentCircuitData a, SimpleRegionInfo reg, IPEndPoint endPoint, bool newAgent);
private void InformClientOfNeighbourCompleted(IAsyncResult iar)
{
@ -274,8 +274,12 @@ namespace OpenSim.Region.Environment.Scenes
/// <param name="regionHandle"></param>
/// <param name="endPoint"></param>
private void InformClientOfNeighbourAsync(ScenePresence avatar, AgentCircuitData a, SimpleRegionInfo reg,
IPEndPoint endPoint)
IPEndPoint endPoint, bool newAgent)
{
// Let's wait just a little to give time to originating regions to catch up with closing child agents
// after a cross here
Thread.Sleep(200);
uint x, y;
Utils.LongToUInts(reg.RegionHandle, out x, out y);
x = x / Constants.RegionSize;
@ -287,7 +291,7 @@ namespace OpenSim.Region.Environment.Scenes
bool regionAccepted = m_commsProvider.InterRegion.InformRegionOfChildAgent(reg.RegionHandle, a);
if (regionAccepted)
if (regionAccepted && newAgent)
{
IEventQueue eq = avatar.Scene.RequestModuleInterface<IEventQueue>();
if (eq != null)
@ -362,6 +366,7 @@ namespace OpenSim.Region.Environment.Scenes
/// Collect as many seeds as possible
Dictionary<ulong, string> seeds = new Dictionary<ulong, string>(avatar.Scene.GetChildrenSeeds(avatar.UUID));
//Console.WriteLine(" !!! No. of seeds: " + seeds.Count);
if (!seeds.ContainsKey(avatar.Scene.RegionInfo.RegionHandle))
seeds.Add(avatar.Scene.RegionInfo.RegionHandle, avatar.ControllingClient.RequestClientInfo().CapsPath);
@ -369,6 +374,9 @@ namespace OpenSim.Region.Environment.Scenes
List<AgentCircuitData> cagents = new List<AgentCircuitData>();
foreach (SimpleRegionInfo neighbour in neighbours)
{
if (neighbour.RegionHandle != avatar.Scene.RegionInfo.RegionHandle)
{
AgentCircuitData agent = avatar.ControllingClient.RequestClientInfo();
agent.BaseFolder = UUID.Zero;
agent.InventoryFolder = UUID.Zero;
@ -386,6 +394,7 @@ namespace OpenSim.Region.Environment.Scenes
cagents.Add(agent);
}
}
/// Update all child agent with everyone's seeds
foreach (AgentCircuitData a in cagents)
@ -398,16 +407,22 @@ namespace OpenSim.Region.Environment.Scenes
//avatar.Scene.DumpChildrenSeeds(avatar.UUID);
//avatar.DumpKnownRegions();
bool newAgent = false;
int count = 0;
foreach (SimpleRegionInfo neighbour in neighbours)
{
// Don't do it if there's already an agent in that region
if (newRegions.Contains(neighbour.RegionHandle))
newAgent = true;
else
newAgent = false;
if (neighbour.RegionHandle != avatar.Scene.RegionInfo.RegionHandle)
{
InformClientOfNeighbourDelegate d = InformClientOfNeighbourAsync;
try
{
d.BeginInvoke(avatar, cagents[count], neighbour, neighbour.ExternalEndPoint,
d.BeginInvoke(avatar, cagents[count], neighbour, neighbour.ExternalEndPoint, newAgent,
InformClientOfNeighbourCompleted,
d);
}
@ -429,11 +444,7 @@ namespace OpenSim.Region.Environment.Scenes
}
}
else
m_log.Debug("[SCM]: Skipping common neighbor " + neighbour.RegionLocX + ", " + neighbour.RegionLocY);
count++;
}
}
@ -450,7 +461,7 @@ namespace OpenSim.Region.Environment.Scenes
agent.child = true;
InformClientOfNeighbourDelegate d = InformClientOfNeighbourAsync;
d.BeginInvoke(avatar, agent, region, region.ExternalEndPoint,
d.BeginInvoke(avatar, agent, region, region.ExternalEndPoint, true,
InformClientOfNeighbourCompleted,
d);
}
@ -748,6 +759,10 @@ namespace OpenSim.Region.Environment.Scenes
// once we reach here...
//avatar.Scene.RemoveCapsHandler(avatar.UUID);
// Let's close some agents
avatar.CloseChildAgents(newRegionX, newRegionY);
string capsPath = String.Empty;
AgentCircuitData agent = avatar.ControllingClient.RequestClientInfo();
agent.BaseFolder = UUID.Zero;
agent.InventoryFolder = UUID.Zero;
@ -757,13 +772,6 @@ namespace OpenSim.Region.Environment.Scenes
{
// brand new agent
agent.CapsPath = Util.GetRandomCapsPath();
}
else
{
// child agent already there
agent.CapsPath = avatar.Scene.GetChildSeed(avatar.UUID, reg.RegionHandle);
}
if (!m_commsProvider.InterRegion.InformRegionOfChildAgent(reg.RegionHandle, agent))
{
avatar.ControllingClient.SendTeleportFailed("Destination is not accepting teleports.");
@ -771,7 +779,7 @@ namespace OpenSim.Region.Environment.Scenes
}
// TODO Should construct this behind a method
string capsPath =
capsPath =
"http://" + reg.ExternalHostName + ":" + reg.HttpPort
+ "/CAPS/" + agent.CapsPath + "0000/";
@ -787,6 +795,14 @@ namespace OpenSim.Region.Environment.Scenes
{
avatar.ControllingClient.InformClientOfNeighbour(reg.RegionHandle, reg.ExternalEndPoint);
}
}
else
{
agent.CapsPath = avatar.Scene.GetChildSeed(avatar.UUID, reg.RegionHandle);
capsPath = "http://" + reg.ExternalHostName + ":" + reg.HttpPort
+ "/CAPS/" + agent.CapsPath + "0000/";
}
if (!m_commsProvider.InterRegion.ExpectAvatarCrossing(reg.RegionHandle, avatar.ControllingClient.AgentId,
position, false))
@ -826,25 +842,26 @@ namespace OpenSim.Region.Environment.Scenes
}
// Let's close some children agents
avatar.CloseChildAgents(newRegionX, newRegionY);
// Close this ScenePresence too
//avatar.Close();
// Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone
//if (Util.IsOutsideView(oldRegionX, newRegionX, oldRegionY, newRegionY))
//{
// CloseConnection(avatar.UUID);
//}
if (Util.IsOutsideView(oldRegionX, newRegionX, oldRegionY, newRegionY))
{
CloseConnection(avatar.UUID);
}
// if (teleport success) // seems to be always success here
// the user may change their profile information in other region,
// so the userinfo in UserProfileCache is not reliable any more, delete it
if (avatar.Scene.NeedSceneCacheClear(avatar.UUID))
{
m_commsProvider.UserProfileCacheService.RemoveUser(avatar.UUID);
m_log.InfoFormat("User {0} is going to another region, profile cache removed", avatar.UUID);
}
// Close this ScenePresence too
//avatar.Close();
}
else
{
avatar.ControllingClient.SendTeleportFailed("Remote Region appears to be down");

View File

@ -505,6 +505,28 @@ namespace OpenSim.Region.Environment.Scenes
}
}
public void AdjustKnownSeeds()
{
Dictionary<ulong, string> seeds = Scene.GetChildrenSeeds(UUID);
List<ulong> old = new List<ulong>();
foreach (ulong handle in seeds.Keys)
{
uint x, y;
Utils.LongToUInts(handle, out x, out y);
x = x / Constants.RegionSize;
y = y / Constants.RegionSize;
if (Util.IsOutsideView(x, Scene.RegionInfo.RegionLocX, y, Scene.RegionInfo.RegionLocY))
{
old.Add(handle);
}
}
DropOldNeighbours(old);
Scene.SetChildrenSeed(UUID, seeds);
KnownRegions = seeds;
//Console.WriteLine(" ++++++++++AFTER+++++++++++++ ");
//DumpKnownRegions();
}
public void DumpKnownRegions()
{
Console.WriteLine("================ KnownRegions {0} ================", Scene.RegionInfo.RegionName);
@ -545,6 +567,7 @@ namespace OpenSim.Region.Environment.Scenes
m_grouptitle = gm.GetGroupTitle(m_uuid);
AbsolutePosition = m_controllingClient.StartPos;
AdjustKnownSeeds();
TrySetMovementAnimation("STAND"); // TODO: I think, this won't send anything, as we are still a child here...
@ -1949,9 +1972,6 @@ namespace OpenSim.Region.Environment.Scenes
CheckForBorderCrossing();
CheckForSignificantMovement(); // sends update to the modules.
}
//if ((x++ % 30) == 0)
// Console.WriteLine(" >> In {0} known regions: {0}, seeds:{1}", Scene.RegionInfo.RegionName, KnownRegions.Count, Scene.GetChildrenSeeds(UUID));
}
#endregion
@ -2412,6 +2432,9 @@ namespace OpenSim.Region.Environment.Scenes
m_physicsActor.Flying);
if (crossingSuccessful)
{
// Next, let's close the child agent connections that are too far away.
CloseChildAgents(neighbourx, neighboury);
AgentCircuitData circuitdata = m_controllingClient.RequestClientInfo();
//Console.WriteLine("BEFORE CROSS");
@ -2446,16 +2469,16 @@ namespace OpenSim.Region.Environment.Scenes
CrossAttachmentsIntoNewRegion(neighbourHandle, true);
// m_scene.SendKillObject(m_localId);
// Next, let's close the child agent connections that are too far away.
CloseChildAgents(neighbourx, neighboury);
m_scene.NotifyMyCoarseLocationChange();
// the user may change their profile information in other region,
// so the userinfo in UserProfileCache is not reliable any more, delete it
if (m_scene.NeedSceneCacheClear(UUID))
{
m_scene.CommsManager.UserProfileCacheService.RemoveUser(UUID);
m_log.InfoFormat("[AVATAR]: User {0} is going to another region, profile cache removed", UUID);
}
}
else
{
// Restore the user structures that we needed to delete before asking the receiving region to complete the crossing
@ -2486,6 +2509,9 @@ namespace OpenSim.Region.Environment.Scenes
lock (m_knownChildRegions)
{
foreach (ulong handle in m_knownChildRegions.Keys)
{
// Don't close the agent on this region yet
if (handle != Scene.RegionInfo.RegionHandle)
{
uint x, y;
Utils.LongToUInts(handle, out x, out y);
@ -2500,6 +2526,7 @@ namespace OpenSim.Region.Environment.Scenes
}
}
}
}
if (byebyeRegions.Count > 0)
{
m_log.Info("[AVATAR]: Closing " + byebyeRegions.Count + " child agents");
@ -2510,7 +2537,6 @@ namespace OpenSim.Region.Environment.Scenes
RemoveNeighbourRegion(handle);
}
}
#endregion