From 03993d0b14599358ac30a001cebd5b2145881c65 Mon Sep 17 00:00:00 2001
From: Justin Clark-Casey (justincc)
Date: Wed, 2 Nov 2011 18:12:12 +0000
Subject: Fix race condition that would sometimes send or save appearance for
the wrong avatar.
In AvatarFactoryModule.HandleAppearanceUpdateTimer(), we loop through appearance save and send requests and dispatch via a FireAndForget thread.
If there was more than one request in the save or send queue, then this led to a subtle race condition where the foreach loop would load in the next KeyValuePair before the thread was dispatched.
This gave the thread the wrong avatar ID, leaving some avatar appearance cloudy since appearance data was never sent.
This change loads the fields into local references so that this doesn't happen.
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
(limited to 'OpenSim/Region/Framework')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 29966f9..3e3fb0f 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -2628,7 +2628,8 @@ namespace OpenSim.Region.Framework.Scenes
///
public void SendAppearanceToAllOtherAgents()
{
- //m_log.DebugFormat("[SCENE PRESENCE] SendAppearanceToAllOtherAgents: {0} ({1})", Name, UUID);
+// m_log.DebugFormat("[SCENE PRESENCE] SendAppearanceToAllOtherAgents: {0} {1}", Name, UUID);
+
// only send update from root agents to other clients; children are only "listening posts"
if (IsChildAgent)
{
@@ -2656,7 +2657,7 @@ namespace OpenSim.Region.Framework.Scenes
///
public void SendOtherAgentsAppearanceToMe()
{
- //m_log.DebugFormat("[SCENE PRESENCE] SendOtherAgentsAppearanceToMe: {0} ({1})", Name, UUID);
+// m_log.DebugFormat("[SCENE PRESENCE] SendOtherAgentsAppearanceToMe: {0} {1}", Name, UUID);
int count = 0;
m_scene.ForEachRootScenePresence(delegate(ScenePresence scenePresence)
--
cgit v1.1
From e2c51a977d42822fe78ae0744117afb7bf509d35 Mon Sep 17 00:00:00 2001
From: Dan Lake
Date: Wed, 2 Nov 2011 14:59:00 -0700
Subject: Changes UpdateFlag in SOP to an enumeration of NONE, TERSE and FULL.
UpdateFlag is now referenced/used only within SOP and SOG. Outsiders are
using ScheduleFullUpdate, ScheduleTerseUpdate or ClearUpdateSchedule on SOP
consistently now. Also started working toward eliminating those calls to
ScheduleFullUpdate, ScheduleTerseUpdate or ClearUpdateSchedule from outside
SOP in favor of just setting properties on SOP and let SOP decide if an
update should be scheduled. This consolidates the update policy within SOP
and the client rather than everywhere that makes changes to SOP. Some places
forget to call update while others call it multiple times, "just to be sure".
UpdateFlag and Schedule*Update will both be made private shortly.
UpdateFlag is intended to be transient and internal to SOP so it has
been removed from XML serializer for SOPs.
---
OpenSim/Region/Framework/Scenes/SceneGraph.cs | 2 +-
.../Region/Framework/Scenes/SceneObjectGroup.cs | 6 +-
OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 101 +++++++++++----------
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 2 +-
.../Scenes/Serialization/SceneObjectSerializer.cs | 7 --
.../Scenes/Tests/SceneObjectLinkingTests.cs | 16 ++--
OpenSim/Region/Framework/Scenes/UndoState.cs | 6 +-
7 files changed, 66 insertions(+), 74 deletions(-)
(limited to 'OpenSim/Region/Framework')
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index 1af18e7..82ded28 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -1799,7 +1799,7 @@ namespace OpenSim.Region.Framework.Scenes
newSet.RemoveAt(0);
foreach (SceneObjectPart newChild in newSet)
- newChild.UpdateFlag = 0;
+ newChild.ClearUpdateSchedule();
LinkObjects(newRoot, newSet);
if (!affectedGroups.Contains(newRoot.ParentGroup))
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 2ea9854..a0a7344 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -1157,7 +1157,7 @@ namespace OpenSim.Region.Framework.Scenes
if (!silent)
{
- part.UpdateFlag = 0;
+ part.ClearUpdateSchedule();
if (part == m_rootPart)
{
if (!IsAttachment || (AttachedAvatar == avatar.ControllingClient.AgentId) ||
@@ -1735,13 +1735,13 @@ namespace OpenSim.Region.Framework.Scenes
if (UsePhysics && !AbsolutePosition.ApproxEquals(lastPhysGroupPos, 0.02f))
{
- m_rootPart.UpdateFlag = 1;
+ m_rootPart.UpdateFlag = UpdateRequired.TERSE;
lastPhysGroupPos = AbsolutePosition;
}
if (UsePhysics && !GroupRotation.ApproxEquals(lastPhysGroupRot, 0.1f))
{
- m_rootPart.UpdateFlag = 1;
+ m_rootPart.UpdateFlag = UpdateRequired.TERSE;
lastPhysGroupRot = GroupRotation;
}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index b68cc9f..44f822c 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -106,6 +106,13 @@ namespace OpenSim.Region.Framework.Scenes
SCULPT = 7
}
+ public enum UpdateRequired : byte
+ {
+ NONE = 0,
+ TERSE = 1,
+ FULL = 2
+ }
+
#endregion Enumerations
public class SceneObjectPart : IScriptHost, ISceneEntity
@@ -254,15 +261,7 @@ namespace OpenSim.Region.Framework.Scenes
private bool m_passTouches;
- ///
- /// 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
- ///
- private byte m_updateFlag;
+ private UpdateRequired m_updateFlag;
private PhysicsActor m_physActor;
protected Vector3 m_acceleration;
@@ -884,7 +883,15 @@ namespace OpenSim.Region.Framework.Scenes
}
}
- ///
+ /// Update angular velocity and schedule terse update.
+ public void UpdateAngularVelocity(Vector3 avel)
+ {
+ AngularVelocity = avel;
+ ScheduleTerseUpdate();
+ ParentGroup.HasGroupChanged = true;
+ }
+
+ /// Get or set angular velocity. Does not schedule update.
public Vector3 AngularVelocity
{
get
@@ -1023,8 +1030,8 @@ namespace OpenSim.Region.Framework.Scenes
TriggerScriptChangedEvent(Changed.SCALE);
}
}
-
- public byte UpdateFlag
+
+ public UpdateRequired UpdateFlag
{
get { return m_updateFlag; }
set { m_updateFlag = value; }
@@ -1309,9 +1316,9 @@ namespace OpenSim.Region.Framework.Scenes
///
/// Clear all pending updates of parts to clients
///
- private void ClearUpdateSchedule()
+ public void ClearUpdateSchedule()
{
- m_updateFlag = 0;
+ UpdateFlag = UpdateRequired.NONE;
}
///
@@ -2829,7 +2836,7 @@ namespace OpenSim.Region.Framework.Scenes
TimeStampFull = (uint)timeNow;
}
- m_updateFlag = 2;
+ UpdateFlag = UpdateRequired.FULL;
// m_log.DebugFormat(
// "[SCENE OBJECT PART]: Scheduling full update for {0}, {1} at {2}",
@@ -2845,13 +2852,13 @@ namespace OpenSim.Region.Framework.Scenes
if (m_parentGroup == null)
return;
- if (m_updateFlag < 1)
+ if (UpdateFlag == UpdateRequired.NONE)
{
m_parentGroup.HasGroupChanged = true;
m_parentGroup.QueueForUpdateCheck();
TimeStampTerse = (uint) Util.UnixTimeSinceEpoch();
- m_updateFlag = 1;
+ UpdateFlag = UpdateRequired.TERSE;
// m_log.DebugFormat(
// "[SCENE OBJECT PART]: Scheduling terse update for {0}, {1} at {2}",
@@ -3018,45 +3025,39 @@ namespace OpenSim.Region.Framework.Scenes
const float POSITION_TOLERANCE = 0.05f;
const int TIME_MS_TOLERANCE = 3000;
- if (m_updateFlag == 1)
+ switch (UpdateFlag)
{
- // Throw away duplicate or insignificant updates
- if (!RotationOffset.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE) ||
- !Acceleration.Equals(m_lastAcceleration) ||
- !Velocity.ApproxEquals(m_lastVelocity, VELOCITY_TOLERANCE) ||
- Velocity.ApproxEquals(Vector3.Zero, VELOCITY_TOLERANCE) ||
- !AngularVelocity.ApproxEquals(m_lastAngularVelocity, VELOCITY_TOLERANCE) ||
- !OffsetPosition.ApproxEquals(m_lastPosition, POSITION_TOLERANCE) ||
- Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE)
+ case UpdateRequired.TERSE:
{
- AddTerseUpdateToAllAvatars();
- ClearUpdateSchedule();
-
- // This causes the Scene to 'poll' physical objects every couple of frames
- // bad, so it's been replaced by an event driven method.
- //if ((ObjectFlags & (uint)PrimFlags.Physics) != 0)
- //{
- // Only send the constant terse updates on physical objects!
- //ScheduleTerseUpdate();
- //}
-
- // Update the "last" values
- m_lastPosition = OffsetPosition;
- m_lastRotation = RotationOffset;
- m_lastVelocity = Velocity;
- m_lastAcceleration = Acceleration;
- m_lastAngularVelocity = AngularVelocity;
- m_lastTerseSent = Environment.TickCount;
+ // Throw away duplicate or insignificant updates
+ if (!RotationOffset.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE) ||
+ !Acceleration.Equals(m_lastAcceleration) ||
+ !Velocity.ApproxEquals(m_lastVelocity, VELOCITY_TOLERANCE) ||
+ Velocity.ApproxEquals(Vector3.Zero, VELOCITY_TOLERANCE) ||
+ !AngularVelocity.ApproxEquals(m_lastAngularVelocity, VELOCITY_TOLERANCE) ||
+ !OffsetPosition.ApproxEquals(m_lastPosition, POSITION_TOLERANCE) ||
+ Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE)
+ {
+ AddTerseUpdateToAllAvatars();
+ ClearUpdateSchedule();
+
+ // Update the "last" values
+ m_lastPosition = OffsetPosition;
+ m_lastRotation = RotationOffset;
+ m_lastVelocity = Velocity;
+ m_lastAcceleration = Acceleration;
+ m_lastAngularVelocity = AngularVelocity;
+ m_lastTerseSent = Environment.TickCount;
+ }
+ break;
}
- }
- else
- {
- if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes
+ case UpdateRequired.FULL:
{
AddFullUpdateToAllAvatars();
- ClearUpdateSchedule();
+ break;
}
}
+
ClearUpdateSchedule();
}
@@ -3436,7 +3437,7 @@ namespace OpenSim.Region.Framework.Scenes
_groupID = groupID;
if (client != null)
SendPropertiesToClient(client);
- m_updateFlag = 2;
+ UpdateFlag = UpdateRequired.FULL;
}
///
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 29966f9..71c39b2 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -3211,7 +3211,7 @@ namespace OpenSim.Region.Framework.Scenes
foreach (ISceneObject so in cAgent.AttachmentObjects)
{
((SceneObjectGroup)so).LocalId = 0;
- ((SceneObjectGroup)so).RootPart.UpdateFlag = 0;
+ ((SceneObjectGroup)so).RootPart.ClearUpdateSchedule();
so.SetState(cAgent.AttachmentObjectStates[i++], m_scene);
m_scene.IncomingCreateObject(so);
}
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
index e06a222..60cc788 100644
--- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
+++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
@@ -316,7 +316,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
m_SOPXmlProcessors.Add("ClickAction", ProcessClickAction);
m_SOPXmlProcessors.Add("Shape", ProcessShape);
m_SOPXmlProcessors.Add("Scale", ProcessScale);
- m_SOPXmlProcessors.Add("UpdateFlag", ProcessUpdateFlag);
m_SOPXmlProcessors.Add("SitTargetOrientation", ProcessSitTargetOrientation);
m_SOPXmlProcessors.Add("SitTargetPosition", ProcessSitTargetPosition);
m_SOPXmlProcessors.Add("SitTargetPositionLL", ProcessSitTargetPositionLL);
@@ -584,11 +583,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
obj.Scale = Util.ReadVector(reader, "Scale");
}
- private static void ProcessUpdateFlag(SceneObjectPart obj, XmlTextReader reader)
- {
- obj.UpdateFlag = (byte)reader.ReadElementContentAsInt("UpdateFlag", String.Empty);
- }
-
private static void ProcessSitTargetOrientation(SceneObjectPart obj, XmlTextReader reader)
{
obj.SitTargetOrientation = Util.ReadQuaternion(reader, "SitTargetOrientation");
@@ -1187,7 +1181,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
WriteShape(writer, sop.Shape, options);
WriteVector(writer, "Scale", sop.Scale);
- writer.WriteElementString("UpdateFlag", sop.UpdateFlag.ToString());
WriteQuaternion(writer, "SitTargetOrientation", sop.SitTargetOrientation);
WriteVector(writer, "SitTargetPosition", sop.SitTargetPosition);
WriteVector(writer, "SitTargetPositionLL", sop.SitTargetPositionLL);
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs
index 90cdd7b..a2332bb 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs
@@ -70,8 +70,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests
grp2.UpdateGroupRotationR(Quaternion.CreateFromEulers(180 * Utils.DEG_TO_RAD, 0, 0));
// Required for linking
- grp1.RootPart.UpdateFlag = 0;
- grp2.RootPart.UpdateFlag = 0;
+ grp1.RootPart.ClearUpdateSchedule();
+ grp2.RootPart.ClearUpdateSchedule();
// Link grp2 to grp1. part2 becomes child prim to grp1. grp2 is eliminated.
grp1.LinkToGroup(grp2);
@@ -164,10 +164,10 @@ namespace OpenSim.Region.Framework.Scenes.Tests
grp4.UpdateGroupRotationR(Quaternion.CreateFromEulers(0, 90 * Utils.DEG_TO_RAD, 0));
// Required for linking
- grp1.RootPart.UpdateFlag = 0;
- grp2.RootPart.UpdateFlag = 0;
- grp3.RootPart.UpdateFlag = 0;
- grp4.RootPart.UpdateFlag = 0;
+ grp1.RootPart.ClearUpdateSchedule();
+ grp2.RootPart.ClearUpdateSchedule();
+ grp3.RootPart.ClearUpdateSchedule();
+ grp4.RootPart.ClearUpdateSchedule();
// Link grp2 to grp1. part2 becomes child prim to grp1. grp2 is eliminated.
grp1.LinkToGroup(grp2);
@@ -198,8 +198,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests
}
// Required for linking
- grp1.RootPart.UpdateFlag = 0;
- grp3.RootPart.UpdateFlag = 0;
+ grp1.RootPart.ClearUpdateSchedule();
+ grp3.RootPart.ClearUpdateSchedule();
// root part should have no offset position or rotation
Assert.That(part1.OffsetPosition == Vector3.Zero && part1.RotationOffset == Quaternion.Identity,
diff --git a/OpenSim/Region/Framework/Scenes/UndoState.cs b/OpenSim/Region/Framework/Scenes/UndoState.cs
index d34d8e5..860172c 100644
--- a/OpenSim/Region/Framework/Scenes/UndoState.cs
+++ b/OpenSim/Region/Framework/Scenes/UndoState.cs
@@ -158,6 +158,7 @@ namespace OpenSim.Region.Framework.Scenes
}
else
{
+ // Note: Updating these properties on sop automatically schedules an update if needed
if (Position != Vector3.Zero)
{
// m_log.DebugFormat(
@@ -181,8 +182,6 @@ namespace OpenSim.Region.Framework.Scenes
part.Resize(Scale);
}
-
- part.ScheduleTerseUpdate();
}
part.Undoing = false;
@@ -212,6 +211,7 @@ namespace OpenSim.Region.Framework.Scenes
}
else
{
+ // Note: Updating these properties on sop automatically schedules an update if needed
if (Position != Vector3.Zero)
part.OffsetPosition = Position;
@@ -220,8 +220,6 @@ namespace OpenSim.Region.Framework.Scenes
if (Scale != Vector3.Zero)
part.Resize(Scale);
-
- part.ScheduleTerseUpdate();
}
part.Undoing = false;
--
cgit v1.1