diff --git a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs index b0e81c3863..aeaa4cb2f0 100644 --- a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs +++ b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs @@ -65,7 +65,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule m_isSyncListenerLocal = m_sysConfig.GetBoolean("IsSyncListenerLocal", false); //Setup the PropertyBucketMap - PupolatePropertyBucketMap(m_sysConfig); + PopulatePropertyBucketMap(m_sysConfig); m_active = true; @@ -187,18 +187,24 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule { get { return m_primPropertyBucketMap; } } - private List m_propertyBucketDescription = new List(); + private List m_propertyBucketNames = new List(); public List PropertyBucketDescription { - get { return m_propertyBucketDescription; } + get { return m_propertyBucketNames; } } private RegionSyncListener m_localSyncListener = null; private bool m_synced = false; // Lock is used to synchronize access to the update status and update queues - private object m_updateSceneObjectPartLock = new object(); - private Dictionary m_primUpdates = new Dictionary(); + //private object m_updateSceneObjectPartLock = new object(); + //private Dictionary m_primUpdates = new Dictionary(); + private Dictionary m_primUpdateLocks = new Dictionary(); + private Dictionary> m_primUpdates = new Dictionary>(); + + private delegate void PrimUpdatePerBucketSender(SceneObjectGroup sog, string bucketName); + private Dictionary m_primUpdatesPerBucketSender = new Dictionary(); + private object m_updateScenePresenceLock = new object(); private Dictionary m_presenceUpdates = new Dictionary(); private int m_sendingUpdates=0; @@ -206,56 +212,45 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule private int m_maxNumOfPropertyBuckets; //Read in configuration for which property-bucket each property belongs to, and the description of each bucket - private void PupolatePropertyBucketMap(IConfig config) + private void PopulatePropertyBucketMap(IConfig config) { //We start with a default bucket map. Will add the code to read in configuration from config files later. - PupolatePropertyBuketMapByDefault(); + PopulatePropertyBuketMapByDefault(); //Pass the bucket information to SceneObjectPart. - SceneObjectPart.InitializePropertyBucketInfo(m_primPropertyBucketMap, m_propertyBucketDescription, m_actorID); + SceneObjectPart.InitializePropertyBucketInfo(m_primPropertyBucketMap, m_propertyBucketNames, m_actorID); + + } + + private void PrimUpdatesGeneralBucketSender(SceneObjectGroup sog, string bucketName) + { + sog.UpdateTaintedBucketSyncInfo(bucketName, DateTime.Now.Ticks); //this update the timestamp and clear the taint info of the bucket + string sogxml = SceneObjectSerializer.ToXml2Format(sog); + SymmetricSyncMessage syncMsg = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.UpdatedObject, sogxml); + SendObjectUpdateToRelevantSyncConnectors(sog, syncMsg); + } + + private void PrimUpdatesPhysicsBucketSender(SceneObjectGroup sog, string bucketName) + { + } //If nothing configured in the config file, this is the default settings for grouping properties into different bucket - private void PupolatePropertyBuketMapByDefault() + private void PopulatePropertyBuketMapByDefault() { //by default, there are two property buckets: the "General" bucket and the "Physics" bucket. string generalBucketName = "General"; string physicsBucketName = "Physics"; - m_propertyBucketDescription.Add(generalBucketName); - m_propertyBucketDescription.Add(physicsBucketName); - m_maxNumOfPropertyBuckets = 2; + m_propertyBucketNames.Add(generalBucketName); + m_propertyBucketNames.Add(physicsBucketName); + m_maxNumOfPropertyBuckets = m_propertyBucketNames.Count; - /* - foreach (string pName in SceneObjectPart.PropertyList) - { - switch (pName){ - case "GroupPosition": - case "OffsetPosition": - case "Scale": - case "Velocity": - case "AngularVelocity": - case "RotationOffset": - case "Position": - case "Size": - case "Force": - case "RotationalVelocity": - case "PA_Acceleration": - case "Torque": - case "Orientation": - case "IsPhysical": - case "Flying": - case "Buoyancy": - m_primPropertyBucketMap.Add(pName, physicsBucketName); - break; - default: - //all other properties belong to the "General" bucket. - m_primPropertyBucketMap.Add(pName, generalBucketName); - break; - } - } - * */ + //Linking each bucket with the sender function that serializes the properties in the bucket and send out sync message + m_primUpdatesPerBucketSender.Add("General", PrimUpdatesGeneralBucketSender); + m_primUpdatesPerBucketSender.Add("Physics", PrimUpdatesPhysicsBucketSender); + //Mapping properties to buckets. foreach (SceneObjectPartProperties property in Enum.GetValues(typeof(SceneObjectPartProperties))) { switch (property) @@ -284,6 +279,13 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule break; } } + + //create different lists to keep track which SOP has what properties updated (which bucket of properties) + foreach (string bucketName in m_propertyBucketNames) + { + m_primUpdates.Add(bucketName, new Dictionary()); + m_primUpdateLocks.Add(bucketName, new Object()); + } } private bool IsSyncingWithOtherActors() @@ -293,37 +295,21 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule public void QueueSceneObjectPartForUpdate(SceneObjectPart part) { - //if the last update of the prim is caused by this actor itself, or if the actor is a relay node, then enqueue the update - //if (part.LastUpdateActorID.Equals(m_actorID) || m_isSyncRelay) - bool updated = m_isSyncRelay; - - if (!updated) + + foreach (string bucketName in m_propertyBucketNames) { - /* - foreach (KeyValuePair pair in part.BucketSyncInfoList) - { - if (pair.Value.LastUpdateActorID.Equals(m_actorID)) + if (part.HasPropertyUpdatedLocallyInGivenBucket(bucketName)) + { + lock (m_primUpdateLocks[bucketName]) { - updated = true; - break; + m_primUpdates[bucketName][part.UUID] = part.ParentGroup; } } - * */ - if (part.HasPropertyUpdatedLocally()) - { - updated = true; - } - } - - if(updated) - { - lock (m_updateSceneObjectPartLock) - { - m_primUpdates[part.UUID] = part.ParentGroup; - } } + } + public void QueueScenePresenceForTerseUpdate(ScenePresence presence) { /* @@ -334,6 +320,8 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule * */ } + + //SendSceneUpdates put each update into an outgoing queue of each SyncConnector public void SendSceneUpdates() { @@ -350,20 +338,28 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule return; } - List primUpdates=null; - List presenceUpdates=null; + //List primUpdates=null; + Dictionary> primUpdates = new Dictionary>(); - if (m_primUpdates.Count > 0) + bool updated = false; + //copy the updated SOG list and clear m_primUpdates for immediately future usage + foreach (string bucketName in m_propertyBucketNames) { - lock (m_updateSceneObjectPartLock) + if (m_primUpdates[bucketName].Count > 0) { - primUpdates = new List(m_primUpdates.Values); - //presenceUpdates = new List(m_presenceUpdates.Values); - m_primUpdates.Clear(); - //m_presenceUpdates.Clear(); + lock (m_primUpdateLocks[bucketName]) + { + updated = true; + primUpdates.Add(bucketName, new List(m_primUpdates[bucketName].Values)); + + m_primUpdates[bucketName].Clear(); + + } } } + /* + List presenceUpdates = null; if (m_presenceUpdates.Count > 0) { lock (m_updateScenePresenceLock) @@ -372,8 +368,9 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule m_presenceUpdates.Clear(); } } + * */ - if (primUpdates != null || presenceUpdates != null) + if (updated) { long timeStamp = DateTime.Now.Ticks; @@ -384,18 +381,24 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule // Dan's note: Sending the message when it's first queued would yield lower latency but much higher load on the simulator // as parts may be updated many many times very quickly. Need to implement a higher resolution send in heartbeat - if (primUpdates != null) + foreach (string bucketName in m_propertyBucketNames) { - foreach (SceneObjectGroup sog in primUpdates) + if (primUpdates[bucketName].Count>0) { - //If this is a relay node, or at least one part of the object has the last update caused by this actor, then send the update - sog.UpdateTaintedBucketSyncInfo(timeStamp); - if (m_isSyncRelay || (!sog.IsDeleted && CheckObjectForSendingUpdate(sog))) + foreach (SceneObjectGroup sog in primUpdates[bucketName]) { - //send - string sogxml = SceneObjectSerializer.ToXml2Format(sog); - SymmetricSyncMessage syncMsg = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.UpdatedObject, sogxml); - SendObjectUpdateToRelevantSyncConnectors(sog, syncMsg); + /* + //If this is a relay node, or at least one part of the object has the last update caused by this actor, then send the update + sog.UpdateTaintedBucketSyncInfo(timeStamp); + if (m_isSyncRelay || (!sog.IsDeleted && CheckObjectForSendingUpdate(sog))) + { + //send + string sogxml = SceneObjectSerializer.ToXml2Format(sog); + SymmetricSyncMessage syncMsg = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.UpdatedObject, sogxml); + SendObjectUpdateToRelevantSyncConnectors(sog, syncMsg); + } + * */ + m_primUpdatesPerBucketSender[bucketName](sog, bucketName); } } } diff --git a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/SymmetricSyncMessage.cs b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/SymmetricSyncMessage.cs index cd893b26af..fe61355f20 100755 --- a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/SymmetricSyncMessage.cs +++ b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/SymmetricSyncMessage.cs @@ -29,6 +29,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule Terrain, NewObject, // objects UpdatedObject, // objects + UpdatedBucketProperties, //object properties in one bucket RemovedObject, // objects LinkObject, DelinkObject, diff --git a/OpenSim/Region/Framework/Interfaces/IRegionSyncModule.cs b/OpenSim/Region/Framework/Interfaces/IRegionSyncModule.cs index db3fd98e7a..d6634db0da 100755 --- a/OpenSim/Region/Framework/Interfaces/IRegionSyncModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IRegionSyncModule.cs @@ -68,6 +68,7 @@ namespace OpenSim.Region.Framework.Interfaces //Enqueue updates for scene-objects and scene-presences void QueueSceneObjectPartForUpdate(SceneObjectPart part); void QueueScenePresenceForTerseUpdate(ScenePresence presence); + //void QueueSceneObjectGroupForUpdate(SceneObjectGroup sog); //The folloiwng calls deal with object updates, and will insert each update into an outgoing queue of each SyncConnector void SendSceneUpdates(); diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 9fda389849..36f033c824 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -4114,6 +4114,15 @@ namespace OpenSim.Region.Framework.Scenes } } + public void UpdateTaintedBucketSyncInfo(string bucketName, long timeStamp) + { + foreach (SceneObjectPart part in Parts) + { + part.UpdateTaintedBucketSyncInfo(bucketName, timeStamp); + } + + } + #endregion } } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index a1e8d6280c..9e1adae4bb 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -4957,6 +4957,7 @@ namespace OpenSim.Region.Framework.Scenes //lock for concurrent updates of the timestamp and actorID. private Object m_updateLock = new Object(); private string m_bucketName; + private bool m_bucketTainted = false; public long LastUpdateTimeStamp { @@ -4975,6 +4976,11 @@ namespace OpenSim.Region.Framework.Scenes get { return m_bucketName; } } + public bool Tainted + { + get { return m_bucketTainted; } + } + public BucketSyncInfo(string bucketName) { m_bucketName = bucketName; @@ -4987,15 +4993,23 @@ namespace OpenSim.Region.Framework.Scenes m_bucketName = bucketName; } - public void UpdateSyncInfo(long timeStamp, string actorID) + public void UpdateSyncInfoAndClearTaint(long timeStamp, string actorID) { lock (m_updateLock) { m_lastUpdateTimeStamp = timeStamp; m_lastUpdateActorID = actorID; + m_bucketTainted = false; //clear taint } } + public void TaintBucket() + { + lock (m_updateLock) + { + m_bucketTainted = true; + } + } } /* @@ -5467,10 +5481,12 @@ namespace OpenSim.Region.Framework.Scenes { m_bucketUpdateLocks.Add(bucketName, new Object()); } + /* if (!m_bucketSyncTainted.ContainsKey(bucketName)) { m_bucketSyncTainted.Add(bucketName, false); } + * */ } if (!m_BucketUpdateProcessorRegistered) @@ -5488,22 +5504,18 @@ namespace OpenSim.Region.Framework.Scenes if (m_syncEnabled && m_bucketSyncTainted.Count > 0) { string bucketName = m_primPropertyBucketMap[property]; - m_bucketSyncTainted[bucketName] = true; + //m_bucketSyncTainted[bucketName] = true; + m_bucketSyncInfoList[bucketName].TaintBucket(); } } - public bool HasPropertyUpdatedLocally() + + public bool HasPropertyUpdatedLocallyInGivenBucket(string bucketName) { - bool updatedLocally = false; - foreach (KeyValuePair pair in m_bucketSyncTainted) - { - updatedLocally = pair.Value; - if (updatedLocally) - break; - } - return updatedLocally; + return m_bucketSyncInfoList[bucketName].Tainted; } + /* public void ClearBucketTaint() { @@ -5530,16 +5542,19 @@ namespace OpenSim.Region.Framework.Scenes string bucketName = pair.Key; if (m_bucketSyncTainted[bucketName]) { - m_bucketSyncInfoList[bucketName].UpdateSyncInfo(timeStamp, m_localActorID); - m_bucketSyncTainted[bucketName] = false; + m_bucketSyncInfoList[bucketName].UpdateSyncInfoAndClearTaint(timeStamp, m_localActorID); + //m_bucketSyncTainted[bucketName] = false; } } } } + /// - /// Update the timestamp information of each property bucket, and clear out the taint on each bucket. + /// Update the timestamp information of each property bucket, and clear out the taint on each bucket. This function won't + /// clear the taints. Caller should clear the taints if needed. /// + /// the timestamp value to be set for any updated bucket public void UpdateTaintedBucketSyncInfo(long timeStamp) { if (m_syncEnabled) @@ -5549,13 +5564,24 @@ namespace OpenSim.Region.Framework.Scenes string bucketName = pair.Key; if (m_bucketSyncTainted[bucketName]) { - m_bucketSyncInfoList[bucketName].UpdateSyncInfo(timeStamp, m_localActorID); - m_bucketSyncTainted[bucketName] = false; + m_bucketSyncInfoList[bucketName].UpdateSyncInfoAndClearTaint(timeStamp, m_localActorID); } } } } + public void UpdateTaintedBucketSyncInfo(string bucketName, long timeStamp) + { + if (m_syncEnabled) + { + if (m_bucketSyncTainted[bucketName]) + { + m_bucketSyncInfoList[bucketName].UpdateSyncInfoAndClearTaint(timeStamp, m_localActorID); + //m_bucketSyncTainted[bucketName] = false; + } + } + } + /// /// Update the timestamp and actorID information of the bucket the given property belongs to. /// @@ -5569,7 +5595,7 @@ namespace OpenSim.Region.Framework.Scenes long timeStamp = DateTime.Now.Ticks; if (m_bucketSyncInfoList.ContainsKey(bucketName)) { - m_bucketSyncInfoList[bucketName].UpdateSyncInfo(timeStamp, m_localActorID); + m_bucketSyncInfoList[bucketName].UpdateSyncInfoAndClearTaint(timeStamp, m_localActorID); } else { @@ -5586,7 +5612,7 @@ namespace OpenSim.Region.Framework.Scenes { string bucketName = pair.Key; BucketSyncInfo syncInfo= pair.Value; - syncInfo.UpdateSyncInfo(timeStamp, m_localActorID); + syncInfo.UpdateSyncInfoAndClearTaint(timeStamp, m_localActorID); m_bucketSyncTainted[bucketName] = false; } }