* Fix Mantis 761 (linking and delinking prims rapidly caused prims to 'disappear')

* Root cause was that if two updates occurred in the same second of time, the second one was never sent
* Linking/delinking appears to be okay now
0.6.0-stable
Justin Clarke Casey 2008-03-13 00:22:38 +00:00
parent 27ff09cb2b
commit a4304fb9e6
5 changed files with 55 additions and 19 deletions

View File

@ -206,6 +206,12 @@ namespace OpenSim.Region.Environment.Scenes
} }
} }
/// <summary>
/// Add an entity to the list of prims to process on the next update
/// </summary>
/// <param name="obj">
/// A <see cref="EntityBase"/>
/// </param>
internal void AddToUpdateList(EntityBase obj) internal void AddToUpdateList(EntityBase obj)
{ {
lock (m_updateList) lock (m_updateList)

View File

@ -614,7 +614,7 @@ namespace OpenSim.Region.Environment.Scenes
} }
/// <summary> /// <summary>
/// /// Start the timer which triggers regular scene updates
/// </summary> /// </summary>
public void StartTimer() public void StartTimer()
{ {

View File

@ -247,9 +247,11 @@ namespace OpenSim.Region.Environment.Scenes
public SceneObjectGroup(Scene scene, ulong regionHandle, SceneObjectPart part) public SceneObjectGroup(Scene scene, ulong regionHandle, SceneObjectPart part)
{ {
m_scene = scene; m_scene = scene;
part.SetParent(this); part.SetParent(this);
part.ParentID = 0; part.ParentID = 0;
part.LinkNum = 0; part.LinkNum = 0;
m_parts.Add(part.UUID, part); m_parts.Add(part.UUID, part);
SetPartAsRoot(part); SetPartAsRoot(part);
@ -691,7 +693,7 @@ namespace OpenSim.Region.Environment.Scenes
#region Scheduling #region Scheduling
/// <summary> /// <summary>
/// /// Examine this object's parts to see if they've changed sufficiently to warrant an update
/// </summary> /// </summary>
public override void Update() public override void Update()
{ {
@ -703,6 +705,7 @@ namespace OpenSim.Region.Environment.Scenes
} }
lastPhysGroupPos = AbsolutePosition; lastPhysGroupPos = AbsolutePosition;
} }
if ((Math.Abs(lastPhysGroupRot.W - GroupRotation.W) > 0.1) if ((Math.Abs(lastPhysGroupRot.W - GroupRotation.W) > 0.1)
|| (Math.Abs(lastPhysGroupRot.X - GroupRotation.X) > 0.1) || (Math.Abs(lastPhysGroupRot.X - GroupRotation.X) > 0.1)
|| (Math.Abs(lastPhysGroupRot.Y - GroupRotation.Y) > 0.1) || (Math.Abs(lastPhysGroupRot.Y - GroupRotation.Y) > 0.1)
@ -714,6 +717,7 @@ namespace OpenSim.Region.Environment.Scenes
} }
lastPhysGroupRot = GroupRotation; lastPhysGroupRot = GroupRotation;
} }
foreach (SceneObjectPart part in m_parts.Values) foreach (SceneObjectPart part in m_parts.Values)
{ {
part.SendScheduledUpdates(); part.SendScheduledUpdates();
@ -737,7 +741,7 @@ namespace OpenSim.Region.Environment.Scenes
} }
/// <summary> /// <summary>
/// /// Schedule a full update for every part in this object
/// </summary> /// </summary>
public void ScheduleGroupForFullUpdate() public void ScheduleGroupForFullUpdate()
{ {
@ -910,6 +914,7 @@ namespace OpenSim.Region.Environment.Scenes
linkPart.RotationOffset = new LLQuaternion(newRot.x, newRot.y, newRot.z, newRot.w); linkPart.RotationOffset = new LLQuaternion(newRot.x, newRot.y, newRot.z, newRot.w);
linkPart.ParentID = m_rootPart.LocalId; linkPart.ParentID = m_rootPart.LocalId;
linkPart.LinkNum = m_parts.Count; linkPart.LinkNum = m_parts.Count;
m_parts.Add(linkPart.UUID, linkPart); m_parts.Add(linkPart.UUID, linkPart);
@ -1015,7 +1020,7 @@ namespace OpenSim.Region.Environment.Scenes
//m_rootPart.DoPhysicsPropertyUpdate(m_rootPart.PhysActor.IsPhysical, true); //m_rootPart.DoPhysicsPropertyUpdate(m_rootPart.PhysActor.IsPhysical, true);
//} //}
SceneObjectGroup objectGroup = new SceneObjectGroup(m_scene, m_regionHandle, linkPart); SceneObjectGroup objectGroup = new SceneObjectGroup(m_scene, m_regionHandle, linkPart);
m_scene.AddEntity(objectGroup); m_scene.AddEntity(objectGroup);
@ -1715,6 +1720,9 @@ namespace OpenSim.Region.Environment.Scenes
m_scene.EventManager.TriggerGroupGrab(UUID, offsetPos, remoteClient.AgentId); m_scene.EventManager.TriggerGroupGrab(UUID, offsetPos, remoteClient.AgentId);
} }
/// <summary>
/// Completely delete this group and tell all the scene presences about that deletion.
/// </summary>
public void DeleteGroup() public void DeleteGroup()
{ {
DetachFromBackup(this); DetachFromBackup(this);

View File

@ -132,7 +132,12 @@ namespace OpenSim.Region.Environment.Scenes
[XmlIgnore] public uint TimeStampLastActivity = 0; // Will be used for AutoReturn [XmlIgnore] public uint TimeStampLastActivity = 0; // Will be used for AutoReturn
/// <summary> /// <summary>
/// Only used internally to schedule client updates /// Only used internally to schedule client updates.
/// 0 - no update is scheduled
/// 1 - terse update scheduled
/// 2 - full update scheduled
///
/// TODO - This should be an enumeration
/// </summary> /// </summary>
private byte m_updateFlag; private byte m_updateFlag;
@ -1090,7 +1095,7 @@ namespace OpenSim.Region.Environment.Scenes
#region Update Scheduling #region Update Scheduling
/// <summary> /// <summary>
/// /// Clear all pending updates
/// </summary> /// </summary>
private void ClearUpdateSchedule() private void ClearUpdateSchedule()
{ {
@ -1098,7 +1103,7 @@ namespace OpenSim.Region.Environment.Scenes
} }
/// <summary> /// <summary>
/// /// Schedules this prim for a full update
/// </summary> /// </summary>
public void ScheduleFullUpdate() public void ScheduleFullUpdate()
{ {
@ -1107,6 +1112,7 @@ namespace OpenSim.Region.Environment.Scenes
m_parentGroup.HasGroupChanged = true; m_parentGroup.HasGroupChanged = true;
m_parentGroup.QueueForUpdateCheck(); m_parentGroup.QueueForUpdateCheck();
} }
TimeStampFull = (uint) Util.UnixTimeSinceEpoch(); TimeStampFull = (uint) Util.UnixTimeSinceEpoch();
m_updateFlag = 2; m_updateFlag = 2;
} }
@ -1156,7 +1162,7 @@ namespace OpenSim.Region.Environment.Scenes
} }
/// <summary> /// <summary>
/// /// Tell all the prims which have had updates scheduled
/// </summary> /// </summary>
public void SendScheduledUpdates() public void SendScheduledUpdates()
{ {
@ -1688,7 +1694,10 @@ namespace OpenSim.Region.Environment.Scenes
} }
#region Client Update Methods #region Client Update Methods
/// <summary>
/// Tell all scene presences that they should send updates for this part to their clients
/// </summary>
public void AddFullUpdateToAllAvatars() public void AddFullUpdateToAllAvatars()
{ {
List<ScenePresence> avatars = m_parentGroup.GetScenePresences(); List<ScenePresence> avatars = m_parentGroup.GetScenePresences();
@ -1697,6 +1706,7 @@ namespace OpenSim.Region.Environment.Scenes
avatars[i].QueuePartForUpdate(this); avatars[i].QueuePartForUpdate(this);
} }
} }
public void SendFullUpdateToAllClientsExcept(LLUUID agentID) public void SendFullUpdateToAllClientsExcept(LLUUID agentID)
{ {
List<ScenePresence> avatars = m_parentGroup.GetScenePresences(); List<ScenePresence> avatars = m_parentGroup.GetScenePresences();
@ -1710,6 +1720,8 @@ namespace OpenSim.Region.Environment.Scenes
} }
} }
} }
public void AddFullUpdateToAvatar(ScenePresence presence) public void AddFullUpdateToAvatar(ScenePresence presence)
{ {
presence.QueuePartForUpdate(this); presence.QueuePartForUpdate(this);

View File

@ -418,6 +418,10 @@ namespace OpenSim.Region.Environment.Scenes
#endregion #endregion
/// <summary>
/// Add the part to the queue of parts for which we need to send an update to the client
/// </summary>
/// <param name="part"></param>
public void QueuePartForUpdate(SceneObjectPart part) public void QueuePartForUpdate(SceneObjectPart part)
{ {
//if (InterestList.Contains(part.ParentGroup)) //if (InterestList.Contains(part.ParentGroup))
@ -434,6 +438,11 @@ namespace OpenSim.Region.Environment.Scenes
return m_scene.PermissionsMngr.GenerateClientFlags(m_uuid, ObjectID); return m_scene.PermissionsMngr.GenerateClientFlags(m_uuid, ObjectID);
} }
/// <summary>
/// Send updates to the client about prims which have been placed on the update queue. We don't
/// necessarily send updates for all the parts on the queue, e.g. if an updates with a more recent
/// timestamp has already been sent.
/// </summary>
public void SendPrimUpdates() public void SendPrimUpdates()
{ {
// if (m_scene.QuadTree.GetNodeID(this.AbsolutePosition.X, this.AbsolutePosition.Y) != m_currentQuadNode) // if (m_scene.QuadTree.GetNodeID(this.AbsolutePosition.X, this.AbsolutePosition.Y) != m_currentQuadNode)
@ -446,13 +455,12 @@ namespace OpenSim.Region.Environment.Scenes
if (!m_gotAllObjectsInScene) if (!m_gotAllObjectsInScene)
{ {
if (!m_isChildAgent || m_scene.m_seeIntoRegionFromNeighbor) if (!m_isChildAgent || m_scene.m_seeIntoRegionFromNeighbor)
{ {
m_scene.SendAllSceneObjectsToClient(this); m_scene.SendAllSceneObjectsToClient(this);
m_gotAllObjectsInScene = true; m_gotAllObjectsInScene = true;
} }
} }
if (m_partsUpdateQueue.Count > 0) if (m_partsUpdateQueue.Count > 0)
{ {
bool runUpdate = true; bool runUpdate = true;
@ -465,16 +473,18 @@ namespace OpenSim.Region.Environment.Scenes
ScenePartUpdate update = m_updateTimes[part.UUID]; ScenePartUpdate update = m_updateTimes[part.UUID];
// Two updates can occur with the same timestamp (especially // Two updates can occur with the same timestamp (especially
// since our timestamp resolution is to the nearest second). The first // since our timestamp resolution is to the nearest second). Therefore, we still need
// could have been sent in the last update - we still need to send the // to send an update even if the last full update time is identical to the part's
// second here. // update timestamp.
//
if (update.LastFullUpdateTime < part.TimeStampFull) // If we don't do this, various events (such as linking and delinking in the same
// second), will stop working properly!
if (update.LastFullUpdateTime <= part.TimeStampFull)
{ {
//need to do a full update //need to do a full update
part.SendFullUpdate(ControllingClient, GenerateClientFlags(part.UUID)); part.SendFullUpdate(ControllingClient, GenerateClientFlags(part.UUID));
// We'll update to the part's timestamp rather than the current to // 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 // avoid the race condition whereby the next tick occurs while we are
// doing this update. If this happened, then subsequent updates which occurred // 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. // on the same tick or the next tick of the last update would be ignored.