From cf24069227f9a32272c873d4423e2e11f5da25a8 Mon Sep 17 00:00:00 2001
From: Mic Bowman
Date: Thu, 3 Feb 2011 12:43:46 -0800
Subject: Change UpdateAgent (for changes in agent position) to be sent once to
each simulator rather than once to each region. This should help with some of
the delays caused by multiple outstanding requests to a single service point.
---
.../Simulation/LocalSimulationConnector.cs | 14 +++---
.../Framework/Scenes/SceneCommunicationService.cs | 43 ++++++++---------
.../Simulation/SimulationServiceConnector.cs | 55 ++++++++++++++++++++--
3 files changed, 81 insertions(+), 31 deletions(-)
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
index c5972dd..56720b7 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 f8ff308..837e655 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 c5313fc..cc6bffb 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;
}
///
--
cgit v1.1