diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
index c5972ddf1e..56720b7b7a 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
@@ -225,17 +225,17 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
if (destination == null)
return false;
+ // We limit the number of messages sent for a position change to just one per
+ // simulator so when we receive the update we need to hand it to each of the
+ // scenes; scenes each check to see if the is a scene presence for the avatar
+ // note that we really don't need the GridRegion for this call
foreach (Scene s in m_sceneList)
{
- if (s.RegionInfo.RegionHandle == destination.RegionHandle)
- {
- //m_log.Debug("[LOCAL COMMS]: Found region to send ChildAgentUpdate");
- s.IncomingChildAgentDataUpdate(cAgentData);
- return true;
- }
+ //m_log.Debug("[LOCAL COMMS]: Found region to send ChildAgentUpdate");
+ s.IncomingChildAgentDataUpdate(cAgentData);
}
//m_log.Debug("[LOCAL COMMS]: region not found for ChildAgentUpdate");
- return false;
+ return true;
}
public bool RetrieveAgent(GridRegion destination, UUID id, out IAgentData agent)
diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
index f8ff308893..837e65523e 100644
--- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
@@ -193,7 +193,8 @@ namespace OpenSim.Region.Framework.Scenes
}
}
- public delegate void SendChildAgentDataUpdateDelegate(AgentPosition cAgentData, UUID scopeID, ulong regionHandle);
+ public delegate void SendChildAgentDataUpdateDelegate(AgentPosition cAgentData, UUID scopeID, GridRegion dest);
+
///
/// This informs all neighboring regions about the settings of it's child agent.
@@ -202,31 +203,17 @@ namespace OpenSim.Region.Framework.Scenes
/// This contains information, such as, Draw Distance, Camera location, Current Position, Current throttle settings, etc.
///
///
- private void SendChildAgentDataUpdateAsync(AgentPosition cAgentData, UUID scopeID, ulong regionHandle)
+ private void SendChildAgentDataUpdateAsync(AgentPosition cAgentData, UUID scopeID, GridRegion dest)
{
//m_log.Info("[INTERGRID]: Informing neighbors about my agent in " + m_regionInfo.RegionName);
try
{
- //m_commsProvider.InterRegion.ChildAgentUpdate(regionHandle, cAgentData);
- uint x = 0, y = 0;
- Utils.LongToUInts(regionHandle, out x, out y);
- GridRegion destination = m_scene.GridService.GetRegionByPosition(UUID.Zero, (int)x, (int)y);
- m_scene.SimulationService.UpdateAgent(destination, cAgentData);
+ m_scene.SimulationService.UpdateAgent(dest, cAgentData);
}
catch
{
// Ignore; we did our best
}
-
- //if (regionAccepted)
- //{
- // //m_log.Info("[INTERGRID]: Completed sending a neighbor an update about my agent");
- //}
- //else
- //{
- // //m_log.Info("[INTERGRID]: Failed sending a neighbor an update about my agent");
- //}
-
}
private void SendChildAgentDataUpdateCompleted(IAsyncResult iar)
@@ -240,14 +227,28 @@ namespace OpenSim.Region.Framework.Scenes
// This assumes that we know what our neighbors are.
try
{
+ uint x = 0, y = 0;
+ List simulatorList = new List();
foreach (ulong regionHandle in presence.KnownChildRegionHandles)
{
if (regionHandle != m_regionInfo.RegionHandle)
{
- SendChildAgentDataUpdateDelegate d = SendChildAgentDataUpdateAsync;
- d.BeginInvoke(cAgentData, m_regionInfo.ScopeID, regionHandle,
- SendChildAgentDataUpdateCompleted,
- d);
+ // we only want to send one update to each simulator; the simulator will
+ // hand it off to the regions where a child agent exists, this does assume
+ // that the region position is cached or performance will degrade
+ Utils.LongToUInts(regionHandle, out x, out y);
+ GridRegion dest = m_scene.GridService.GetRegionByPosition(UUID.Zero, (int)x, (int)y);
+ if (! simulatorList.Contains(dest.ServerURI))
+ {
+ // we havent seen this simulator before, add it to the list
+ // and send it an update
+ simulatorList.Add(dest.ServerURI);
+
+ SendChildAgentDataUpdateDelegate d = SendChildAgentDataUpdateAsync;
+ d.BeginInvoke(cAgentData, m_regionInfo.ScopeID, dest,
+ SendChildAgentDataUpdateCompleted,
+ d);
+ }
}
}
}
diff --git a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs
index c5313fc8b9..cc6bffb7bb 100644
--- a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs
+++ b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs
@@ -48,6 +48,9 @@ namespace OpenSim.Services.Connectors.Simulation
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+ // we use this dictionary to track the pending updateagent requests, maps URI --> position update
+ private Dictionary m_updateAgentQueue = new Dictionary();
+
//private GridRegion m_Region;
public SimulationServiceConnector()
@@ -133,10 +136,56 @@ namespace OpenSim.Services.Connectors.Simulation
///
public bool UpdateAgent(GridRegion destination, AgentPosition data)
{
- // we need a better throttle for these
- // return false;
+ // The basic idea of this code is that the first thread that needs to
+ // send an update for a specific avatar becomes the worker for any subsequent
+ // requests until there are no more outstanding requests. Further, only send the most
+ // recent update; this *should* never be needed but some requests get
+ // slowed down and once that happens the problem with service end point
+ // limits kicks in and nothing proceeds
+ string uri = destination.ServerURI + AgentPath() + data.AgentID + "/";
+ lock (m_updateAgentQueue)
+ {
+ if (m_updateAgentQueue.ContainsKey(uri))
+ {
+ // Another thread is already handling
+ // updates for this simulator, just update
+ // the position and return, overwrites are
+ // not a problem since we only care about the
+ // last update anyway
+ m_updateAgentQueue[uri] = data;
+ return true;
+ }
+
+ // Otherwise update the reference and start processing
+ m_updateAgentQueue[uri] = data;
+ }
- return UpdateAgent(destination, (IAgentData)data);
+ AgentPosition pos = null;
+ while (true)
+ {
+ lock (m_updateAgentQueue)
+ {
+ // save the position
+ AgentPosition lastpos = pos;
+
+ pos = m_updateAgentQueue[uri];
+
+ // this is true if no one put a new
+ // update in the map since the last
+ // one we processed, if thats the
+ // case then we are done
+ if (pos == lastpos)
+ {
+ m_updateAgentQueue.Remove(uri);
+ return true;
+ }
+ }
+
+ UpdateAgent(destination,(IAgentData)pos);
+ }
+
+ // unreachable
+ return true;
}
///