Patch #9163 - Refactor initial packet sending out of InnerScene into

ScenePresence. Pace prim delivery to about 200 updates/s max. Break
a long-held lock that caused the notorious MapBlockQuery XMLRPC timeout
on agent login. Eliminate 60 second timeout at "Waiting for region handshake".
Fix region crossing/teleport response. Fix appearance in primmy regions.
0.6.0-stable
Melanie Thielker 2008-08-11 23:20:14 +00:00
parent b627c9c066
commit f9945bf87f
3 changed files with 74 additions and 129 deletions

View File

@ -954,43 +954,6 @@ namespace OpenSim.Region.Environment.Scenes
return LLUUID.Zero; return LLUUID.Zero;
} }
protected internal void SendAllSceneObjectsToClient(ScenePresence presence)
{
List<EntityBase> EntityList = GetEntities();
foreach (EntityBase ent in EntityList)
{
if (ent is SceneObjectGroup)
{
// Only send child agents stuff in their draw distance.
// This will need to be done for every agent once we figure out
// what we're going to use to store prim that agents already got
// the initial update for and what we'll use to limit the
// space we check for new objects on movement.
if (presence.IsChildAgent && m_parentScene.m_seeIntoRegionFromNeighbor)
{
LLVector3 oLoc = ((SceneObjectGroup)ent).AbsolutePosition;
float distResult = (float)Util.GetDistanceTo(presence.AbsolutePosition, oLoc);
//m_log.Info("[DISTANCE]: " + distResult.ToString());
if (distResult < presence.DrawDistance)
{
// Send Only if we don't already know about it.
// KnownPrim also makes the prim known when called.
if (!presence.KnownPrim(((SceneObjectGroup)ent).UUID))
((SceneObjectGroup)ent).ScheduleFullUpdateToAvatar(presence);
}
}
else
{
((SceneObjectGroup)ent).ScheduleFullUpdateToAvatar(presence);
}
}
}
}
protected internal void ForEachClient(Action<IClientAPI> action) protected internal void ForEachClient(Action<IClientAPI> action)
{ {
lock (ScenePresences) lock (ScenePresences)

View File

@ -3498,15 +3498,6 @@ namespace OpenSim.Region.Environment.Scenes
m_innerScene.RemovePhysicalPrim(num); m_innerScene.RemovePhysicalPrim(num);
} }
/// <summary>
///
/// </summary>
/// <param name="presence"></param>
public void SendAllSceneObjectsToClient(ScenePresence presence)
{
m_innerScene.SendAllSceneObjectsToClient(presence);
}
//The idea is to have a group of method that return a list of avatars meeting some requirement //The idea is to have a group of method that return a list of avatars meeting some requirement
// ie it could be all m_scenePresences within a certain range of the calling prim/avatar. // ie it could be all m_scenePresences within a certain range of the calling prim/avatar.

View File

@ -128,7 +128,6 @@ namespace OpenSim.Region.Environment.Scenes
// Agent moves with a PID controller causing a force to be exerted. // Agent moves with a PID controller causing a force to be exerted.
private bool m_newForce = false; private bool m_newForce = false;
private bool m_newCoarseLocations = true; private bool m_newCoarseLocations = true;
private bool m_gotAllObjectsInScene = false;
private float m_health = 100f; private float m_health = 100f;
private LLVector3 m_lastVelocity = LLVector3.Zero; private LLVector3 m_lastVelocity = LLVector3.Zero;
@ -161,8 +160,6 @@ namespace OpenSim.Region.Environment.Scenes
private LLVector3 m_autoPilotTarget = LLVector3.Zero; private LLVector3 m_autoPilotTarget = LLVector3.Zero;
private bool m_sitAtAutoTarget = false; private bool m_sitAtAutoTarget = false;
private List<LLUUID> m_knownPrimUUID = new List<LLUUID>();
// Agent's Draw distance. // Agent's Draw distance.
protected float m_DrawDistance = 0f; protected float m_DrawDistance = 0f;
@ -193,6 +190,8 @@ namespace OpenSim.Region.Environment.Scenes
private LLVector3 posLastSignificantMove = new LLVector3(); private LLVector3 posLastSignificantMove = new LLVector3();
private UpdateQueue m_partsUpdateQueue = new UpdateQueue(); private UpdateQueue m_partsUpdateQueue = new UpdateQueue();
private Queue<SceneObjectGroup> m_pendingObjects = null;
private Dictionary<LLUUID, ScenePartUpdate> m_updateTimes = new Dictionary<LLUUID, ScenePartUpdate>(); private Dictionary<LLUUID, ScenePartUpdate> m_updateTimes = new Dictionary<LLUUID, ScenePartUpdate>();
#region Properties #region Properties
@ -212,16 +211,6 @@ namespace OpenSim.Region.Environment.Scenes
get { return m_movementflag; } get { return m_movementflag; }
} }
public bool KnownPrim(LLUUID primID)
{
if (m_knownPrimUUID.Contains(primID))
{
return true;
}
m_knownPrimUUID.Add(primID);
return false;
}
public bool Updated public bool Updated
{ {
set { m_updateflag = value; } set { m_updateflag = value; }
@ -508,72 +497,93 @@ namespace OpenSim.Region.Environment.Scenes
//} //}
m_perfMonMS = System.Environment.TickCount; m_perfMonMS = System.Environment.TickCount;
if (!m_gotAllObjectsInScene) if (m_pendingObjects == null)
{ {
if (!m_isChildAgent || m_scene.m_seeIntoRegionFromNeighbor) if (!m_isChildAgent || m_scene.m_seeIntoRegionFromNeighbor)
{ {
m_scene.SendAllSceneObjectsToClient(this); m_pendingObjects = new Queue<SceneObjectGroup>();
m_gotAllObjectsInScene = true;
foreach (EntityBase e in m_scene.Entities.Values)
if(e is SceneObjectGroup)
m_pendingObjects.Enqueue((SceneObjectGroup)e);
} }
} }
if (m_partsUpdateQueue.Count > 0) while(m_pendingObjects.Count > 0 && m_partsUpdateQueue.Count < 60)
{ {
bool runUpdate = true; SceneObjectGroup g = m_pendingObjects.Dequeue();
int updateCount = 0;
while (runUpdate)
{
SceneObjectPart part = m_partsUpdateQueue.Dequeue();
if (m_updateTimes.ContainsKey(part.UUID))
{
ScenePartUpdate update = m_updateTimes[part.UUID];
// We deal with the possibility that two updates occur at the same unix time // This is where we should check for draw distance
// at the update point itself. // do culling and stuff. Problem with that is that until
if (update.LastFullUpdateTime < part.TimeStampFull) // we recheck in movement, that won't work right.
{ // So it's not implemented now.
//
// Don't even queue if we have seent this one
//
if (!m_updateTimes.ContainsKey(g.UUID))
g.ScheduleFullUpdateToAvatar(this);
}
int updateCount = 0;
while (m_partsUpdateQueue.Count > 0)
{
SceneObjectPart part = m_partsUpdateQueue.Dequeue();
if (m_updateTimes.ContainsKey(part.UUID))
{
ScenePartUpdate update = m_updateTimes[part.UUID];
// We deal with the possibility that two updates occur at
// the same unix time at the update point itself.
if (update.LastFullUpdateTime < part.TimeStampFull)
{
// m_log.DebugFormat( // m_log.DebugFormat(
// "[SCENE PRESENCE]: Fully updating prim {0}, {1} - part timestamp {2}", // "[SCENE PRESENCE]: Fully updating prim {0}, {1} - part timestamp {2}",
// part.Name, part.UUID, part.TimeStampFull); // part.Name, part.UUID, part.TimeStampFull);
part.SendFullUpdate(ControllingClient, GenerateClientFlags(part.UUID)); part.SendFullUpdate(ControllingClient,
GenerateClientFlags(part.UUID));
// We'll update to the part's timestamp rather than the current time to // We'll update to the part's timestamp rather than
// avoid the race condition whereby the next tick occurs while we are // the current time to avoid the race condition
// doing this update. If this happened, then subsequent updates which occurred // whereby the next tick occurs while we are doing
// on the same tick or the next tick of the last update would be ignored. // this update. If this happened, then subsequent
update.LastFullUpdateTime = part.TimeStampFull; // updates which occurred on the same tick or the
// next tick of the last update would be ignored.
updateCount++; update.LastFullUpdateTime = part.TimeStampFull;
}
else if (update.LastTerseUpdateTime <= part.TimeStampTerse) updateCount++;
{ }
else if (update.LastTerseUpdateTime <= part.TimeStampTerse)
{
// m_log.DebugFormat( // m_log.DebugFormat(
// "[SCENE PRESENCE]: Tersely updating prim {0}, {1} - part timestamp {2}", // "[SCENE PRESENCE]: Tersely updating prim {0}, {1} - part timestamp {2}",
// part.Name, part.UUID, part.TimeStampTerse); // part.Name, part.UUID, part.TimeStampTerse);
part.SendTerseUpdate(ControllingClient); part.SendTerseUpdate(ControllingClient);
update.LastTerseUpdateTime = part.TimeStampTerse; update.LastTerseUpdateTime = part.TimeStampTerse;
updateCount++;
}
}
else
{
//never been sent to client before so do full update
part.SendFullUpdate(ControllingClient, GenerateClientFlags(part.UUID));
ScenePartUpdate update = new ScenePartUpdate();
update.FullID = part.UUID;
update.LastFullUpdateTime = part.TimeStampFull;
m_updateTimes.Add(part.UUID, update);
updateCount++; updateCount++;
} }
if (m_partsUpdateQueue.Count < 1 || updateCount > 60)
{
runUpdate = false;
}
} }
else
{
//never been sent to client before so do full update
part.SendFullUpdate(ControllingClient,
GenerateClientFlags(part.UUID));
ScenePartUpdate update = new ScenePartUpdate();
update.FullID = part.UUID;
update.LastFullUpdateTime = part.TimeStampFull;
m_updateTimes.Add(part.UUID, update);
updateCount++;
}
if (updateCount > 60)
break;
} }
m_scene.AddAgentTime(System.Environment.TickCount - m_perfMonMS); m_scene.AddAgentTime(System.Environment.TickCount - m_perfMonMS);
@ -631,15 +641,13 @@ namespace OpenSim.Region.Environment.Scenes
m_scene.SwapRootAgentCount(false); m_scene.SwapRootAgentCount(false);
m_scene.CommsManager.UserProfileCacheService.RequestInventoryForUser(m_uuid); m_scene.CommsManager.UserProfileCacheService.RequestInventoryForUser(m_uuid);
m_scene.AddCapsHandler(m_uuid); m_scene.AddCapsHandler(m_uuid);
//if (!m_gotAllObjectsInScene)
//{ // On the next prim update, all objects will be sent
m_scene.SendAllSceneObjectsToClient(this); //
m_pendingObjects = null;
m_scene.EventManager.TriggerOnMakeRootAgent(this); m_scene.EventManager.TriggerOnMakeRootAgent(this);
m_scene.CommsManager.UserService.UpdateUserCurrentRegion(UUID, m_scene.RegionInfo.RegionID, m_scene.RegionInfo.RegionHandle); m_scene.CommsManager.UserService.UpdateUserCurrentRegion(UUID, m_scene.RegionInfo.RegionID, m_scene.RegionInfo.RegionHandle);
//m_gotAllObjectsInScene = true;
//}
} }
/// <summary> /// <summary>
@ -776,7 +784,6 @@ namespace OpenSim.Region.Environment.Scenes
{ {
m_isChildAgent = false; m_isChildAgent = false;
//this.m_scene.SendAllSceneObjectsToClient(this.ControllingClient);
MakeRootAgent(AbsolutePosition, false); MakeRootAgent(AbsolutePosition, false);
} }
} }
@ -2043,7 +2050,8 @@ namespace OpenSim.Region.Environment.Scenes
// Sends out the objects in the user's draw distance if m_sendTasksToChild is true. // Sends out the objects in the user's draw distance if m_sendTasksToChild is true.
if (m_scene.m_seeIntoRegionFromNeighbor) if (m_scene.m_seeIntoRegionFromNeighbor)
m_scene.SendAllSceneObjectsToClient(this); m_pendingObjects = null;
//cAgentData.AVHeight; //cAgentData.AVHeight;
//cAgentData.regionHandle; //cAgentData.regionHandle;
//m_velocity = cAgentData.Velocity; //m_velocity = cAgentData.Velocity;
@ -2248,10 +2256,6 @@ namespace OpenSim.Region.Environment.Scenes
m_attachments.Clear(); m_attachments.Clear();
} }
} }
lock (m_knownPrimUUID)
{
m_knownPrimUUID.Clear();
}
lock (m_knownChildRegions) lock (m_knownChildRegions)
{ {
m_knownChildRegions.Clear(); m_knownChildRegions.Clear();
@ -2398,7 +2402,6 @@ namespace OpenSim.Region.Environment.Scenes
m_newForce = (bool)info.GetValue("m_newForce", typeof(bool)); m_newForce = (bool)info.GetValue("m_newForce", typeof(bool));
//m_newAvatar = (bool)info.GetValue("m_newAvatar", typeof(bool)); //m_newAvatar = (bool)info.GetValue("m_newAvatar", typeof(bool));
m_newCoarseLocations = (bool)info.GetValue("m_newCoarseLocations", typeof(bool)); m_newCoarseLocations = (bool)info.GetValue("m_newCoarseLocations", typeof(bool));
m_gotAllObjectsInScene = (bool)info.GetValue("m_gotAllObjectsInScene", typeof(bool));
m_avHeight = (float)info.GetValue("m_avHeight", typeof(float)); m_avHeight = (float)info.GetValue("m_avHeight", typeof(float));
crossingFromRegion = (ulong)info.GetValue("crossingFromRegion", typeof(ulong)); crossingFromRegion = (ulong)info.GetValue("crossingFromRegion", typeof(ulong));
@ -2503,13 +2506,6 @@ namespace OpenSim.Region.Environment.Scenes
m_state = (byte)info.GetValue("m_state", typeof(byte)); m_state = (byte)info.GetValue("m_state", typeof(byte));
List<Guid> knownPrimUUID_work = (List<Guid>)info.GetValue("m_knownPrimUUID", typeof(List<Guid>));
foreach (Guid id in knownPrimUUID_work)
{
m_knownPrimUUID.Add(new LLUUID(id));
}
//System.Console.WriteLine("ScenePresence Deserialize END"); //System.Console.WriteLine("ScenePresence Deserialize END");
} }
@ -2551,7 +2547,7 @@ namespace OpenSim.Region.Environment.Scenes
info.AddValue("m_newForce", m_newForce); info.AddValue("m_newForce", m_newForce);
//info.AddValue("m_newAvatar", m_newAvatar); //info.AddValue("m_newAvatar", m_newAvatar);
info.AddValue("m_newCoarseLocations", m_newCoarseLocations); info.AddValue("m_newCoarseLocations", m_newCoarseLocations);
info.AddValue("m_gotAllObjectsInScene", m_gotAllObjectsInScene); info.AddValue("m_gotAllObjectsInScene", false);
info.AddValue("m_avHeight", m_avHeight); info.AddValue("m_avHeight", m_avHeight);
// info.AddValue("m_regionInfo", m_regionInfo); // info.AddValue("m_regionInfo", m_regionInfo);
@ -2650,11 +2646,6 @@ namespace OpenSim.Region.Environment.Scenes
List<Guid> knownPrimUUID_work = new List<Guid>(); List<Guid> knownPrimUUID_work = new List<Guid>();
foreach (LLUUID id in m_knownPrimUUID)
{
knownPrimUUID_work.Add(id.UUID);
}
info.AddValue("m_knownPrimUUID", knownPrimUUID_work); info.AddValue("m_knownPrimUUID", knownPrimUUID_work);
} }