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;
}
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)
{
lock (ScenePresences)

View File

@ -3498,15 +3498,6 @@ namespace OpenSim.Region.Environment.Scenes
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
// 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.
private bool m_newForce = false;
private bool m_newCoarseLocations = true;
private bool m_gotAllObjectsInScene = false;
private float m_health = 100f;
private LLVector3 m_lastVelocity = LLVector3.Zero;
@ -161,8 +160,6 @@ namespace OpenSim.Region.Environment.Scenes
private LLVector3 m_autoPilotTarget = LLVector3.Zero;
private bool m_sitAtAutoTarget = false;
private List<LLUUID> m_knownPrimUUID = new List<LLUUID>();
// Agent's Draw distance.
protected float m_DrawDistance = 0f;
@ -193,6 +190,8 @@ namespace OpenSim.Region.Environment.Scenes
private LLVector3 posLastSignificantMove = new LLVector3();
private UpdateQueue m_partsUpdateQueue = new UpdateQueue();
private Queue<SceneObjectGroup> m_pendingObjects = null;
private Dictionary<LLUUID, ScenePartUpdate> m_updateTimes = new Dictionary<LLUUID, ScenePartUpdate>();
#region Properties
@ -212,16 +211,6 @@ namespace OpenSim.Region.Environment.Scenes
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
{
set { m_updateflag = value; }
@ -508,72 +497,93 @@ namespace OpenSim.Region.Environment.Scenes
//}
m_perfMonMS = System.Environment.TickCount;
if (!m_gotAllObjectsInScene)
if (m_pendingObjects == null)
{
if (!m_isChildAgent || m_scene.m_seeIntoRegionFromNeighbor)
{
m_scene.SendAllSceneObjectsToClient(this);
m_gotAllObjectsInScene = true;
m_pendingObjects = new Queue<SceneObjectGroup>();
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;
int updateCount = 0;
while (runUpdate)
{
SceneObjectPart part = m_partsUpdateQueue.Dequeue();
if (m_updateTimes.ContainsKey(part.UUID))
{
ScenePartUpdate update = m_updateTimes[part.UUID];
SceneObjectGroup g = m_pendingObjects.Dequeue();
// We deal with the possibility that two updates occur at the same unix time
// at the update point itself.
if (update.LastFullUpdateTime < part.TimeStampFull)
{
// This is where we should check for draw distance
// do culling and stuff. Problem with that is that until
// 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(
// "[SCENE PRESENCE]: Fully updating prim {0}, {1} - part timestamp {2}",
// 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
// avoid the race condition whereby the next tick occurs while we are
// doing this update. If this happened, then subsequent updates which occurred
// on the same tick or the next tick of the last update would be ignored.
update.LastFullUpdateTime = part.TimeStampFull;
// We'll update to the part's timestamp rather than
// the current time to avoid the race condition
// whereby the next tick occurs while we are doing
// this update. If this happened, then subsequent
// updates which occurred on the same tick or the
// next tick of the last update would be ignored.
updateCount++;
}
else if (update.LastTerseUpdateTime <= part.TimeStampTerse)
{
update.LastFullUpdateTime = part.TimeStampFull;
updateCount++;
}
else if (update.LastTerseUpdateTime <= part.TimeStampTerse)
{
// m_log.DebugFormat(
// "[SCENE PRESENCE]: Tersely updating prim {0}, {1} - part timestamp {2}",
// part.Name, part.UUID, part.TimeStampTerse);
part.SendTerseUpdate(ControllingClient);
part.SendTerseUpdate(ControllingClient);
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);
update.LastTerseUpdateTime = part.TimeStampTerse;
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);
@ -631,15 +641,13 @@ namespace OpenSim.Region.Environment.Scenes
m_scene.SwapRootAgentCount(false);
m_scene.CommsManager.UserProfileCacheService.RequestInventoryForUser(m_uuid);
m_scene.AddCapsHandler(m_uuid);
//if (!m_gotAllObjectsInScene)
//{
m_scene.SendAllSceneObjectsToClient(this);
// On the next prim update, all objects will be sent
//
m_pendingObjects = null;
m_scene.EventManager.TriggerOnMakeRootAgent(this);
m_scene.CommsManager.UserService.UpdateUserCurrentRegion(UUID, m_scene.RegionInfo.RegionID, m_scene.RegionInfo.RegionHandle);
//m_gotAllObjectsInScene = true;
//}
}
/// <summary>
@ -776,7 +784,6 @@ namespace OpenSim.Region.Environment.Scenes
{
m_isChildAgent = false;
//this.m_scene.SendAllSceneObjectsToClient(this.ControllingClient);
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.
if (m_scene.m_seeIntoRegionFromNeighbor)
m_scene.SendAllSceneObjectsToClient(this);
m_pendingObjects = null;
//cAgentData.AVHeight;
//cAgentData.regionHandle;
//m_velocity = cAgentData.Velocity;
@ -2248,10 +2256,6 @@ namespace OpenSim.Region.Environment.Scenes
m_attachments.Clear();
}
}
lock (m_knownPrimUUID)
{
m_knownPrimUUID.Clear();
}
lock (m_knownChildRegions)
{
m_knownChildRegions.Clear();
@ -2398,7 +2402,6 @@ namespace OpenSim.Region.Environment.Scenes
m_newForce = (bool)info.GetValue("m_newForce", typeof(bool));
//m_newAvatar = (bool)info.GetValue("m_newAvatar", 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));
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));
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");
}
@ -2551,7 +2547,7 @@ namespace OpenSim.Region.Environment.Scenes
info.AddValue("m_newForce", m_newForce);
//info.AddValue("m_newAvatar", m_newAvatar);
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_regionInfo", m_regionInfo);
@ -2650,11 +2646,6 @@ namespace OpenSim.Region.Environment.Scenes
List<Guid> knownPrimUUID_work = new List<Guid>();
foreach (LLUUID id in m_knownPrimUUID)
{
knownPrimUUID_work.Add(id.UUID);
}
info.AddValue("m_knownPrimUUID", knownPrimUUID_work);
}