In RegionSyncModule, now each property bucket has its own list of updated-prims.

An SOP will be inserted (now it's still its parent group will be inserted) into a bucket
if that bucket has been tained as updated.

Also, added Tainted property to BucketSyncInfo.
dsg
Huaiyu (Kitty) Liu 2011-02-14 17:08:49 -08:00
parent f05502f3fe
commit 7229aa204e
5 changed files with 141 additions and 101 deletions

View File

@ -65,7 +65,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
m_isSyncListenerLocal = m_sysConfig.GetBoolean("IsSyncListenerLocal", false); m_isSyncListenerLocal = m_sysConfig.GetBoolean("IsSyncListenerLocal", false);
//Setup the PropertyBucketMap //Setup the PropertyBucketMap
PupolatePropertyBucketMap(m_sysConfig); PopulatePropertyBucketMap(m_sysConfig);
m_active = true; m_active = true;
@ -187,18 +187,24 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
{ {
get { return m_primPropertyBucketMap; } get { return m_primPropertyBucketMap; }
} }
private List<string> m_propertyBucketDescription = new List<string>(); private List<string> m_propertyBucketNames = new List<string>();
public List<string> PropertyBucketDescription public List<string> PropertyBucketDescription
{ {
get { return m_propertyBucketDescription; } get { return m_propertyBucketNames; }
} }
private RegionSyncListener m_localSyncListener = null; private RegionSyncListener m_localSyncListener = null;
private bool m_synced = false; private bool m_synced = false;
// Lock is used to synchronize access to the update status and update queues // Lock is used to synchronize access to the update status and update queues
private object m_updateSceneObjectPartLock = new object(); //private object m_updateSceneObjectPartLock = new object();
private Dictionary<UUID, SceneObjectGroup> m_primUpdates = new Dictionary<UUID, SceneObjectGroup>(); //private Dictionary<UUID, SceneObjectGroup> m_primUpdates = new Dictionary<UUID, SceneObjectGroup>();
private Dictionary<string, Object> m_primUpdateLocks = new Dictionary<string, object>();
private Dictionary<string, Dictionary<UUID, SceneObjectGroup>> m_primUpdates = new Dictionary<string, Dictionary<UUID, SceneObjectGroup>>();
private delegate void PrimUpdatePerBucketSender(SceneObjectGroup sog, string bucketName);
private Dictionary<string,PrimUpdatePerBucketSender> m_primUpdatesPerBucketSender = new Dictionary<string,PrimUpdatePerBucketSender>();
private object m_updateScenePresenceLock = new object(); private object m_updateScenePresenceLock = new object();
private Dictionary<UUID, ScenePresence> m_presenceUpdates = new Dictionary<UUID, ScenePresence>(); private Dictionary<UUID, ScenePresence> m_presenceUpdates = new Dictionary<UUID, ScenePresence>();
private int m_sendingUpdates=0; private int m_sendingUpdates=0;
@ -206,56 +212,45 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
private int m_maxNumOfPropertyBuckets; private int m_maxNumOfPropertyBuckets;
//Read in configuration for which property-bucket each property belongs to, and the description of each bucket //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. //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. //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 //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. //by default, there are two property buckets: the "General" bucket and the "Physics" bucket.
string generalBucketName = "General"; string generalBucketName = "General";
string physicsBucketName = "Physics"; string physicsBucketName = "Physics";
m_propertyBucketDescription.Add(generalBucketName); m_propertyBucketNames.Add(generalBucketName);
m_propertyBucketDescription.Add(physicsBucketName); m_propertyBucketNames.Add(physicsBucketName);
m_maxNumOfPropertyBuckets = 2; m_maxNumOfPropertyBuckets = m_propertyBucketNames.Count;
/* //Linking each bucket with the sender function that serializes the properties in the bucket and send out sync message
foreach (string pName in SceneObjectPart.PropertyList) m_primUpdatesPerBucketSender.Add("General", PrimUpdatesGeneralBucketSender);
{ m_primUpdatesPerBucketSender.Add("Physics", PrimUpdatesPhysicsBucketSender);
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;
}
}
* */
//Mapping properties to buckets.
foreach (SceneObjectPartProperties property in Enum.GetValues(typeof(SceneObjectPartProperties))) foreach (SceneObjectPartProperties property in Enum.GetValues(typeof(SceneObjectPartProperties)))
{ {
switch (property) switch (property)
@ -284,6 +279,13 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
break; 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<UUID, SceneObjectGroup>());
m_primUpdateLocks.Add(bucketName, new Object());
}
} }
private bool IsSyncingWithOtherActors() private bool IsSyncingWithOtherActors()
@ -293,37 +295,21 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
public void QueueSceneObjectPartForUpdate(SceneObjectPart part) 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) foreach (string bucketName in m_propertyBucketNames)
bool updated = m_isSyncRelay;
if (!updated)
{ {
/* if (part.HasPropertyUpdatedLocallyInGivenBucket(bucketName))
foreach (KeyValuePair<string, BucketSyncInfo> pair in part.BucketSyncInfoList) {
{ lock (m_primUpdateLocks[bucketName])
if (pair.Value.LastUpdateActorID.Equals(m_actorID))
{ {
updated = true; m_primUpdates[bucketName][part.UUID] = part.ParentGroup;
break;
} }
} }
* */
if (part.HasPropertyUpdatedLocally())
{
updated = true;
}
}
if(updated)
{
lock (m_updateSceneObjectPartLock)
{
m_primUpdates[part.UUID] = part.ParentGroup;
}
} }
} }
public void QueueScenePresenceForTerseUpdate(ScenePresence presence) 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 //SendSceneUpdates put each update into an outgoing queue of each SyncConnector
public void SendSceneUpdates() public void SendSceneUpdates()
{ {
@ -350,20 +338,28 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
return; return;
} }
List<SceneObjectGroup> primUpdates=null; //List<SceneObjectGroup> primUpdates=null;
List<ScenePresence> presenceUpdates=null; Dictionary<string, List<SceneObjectGroup>> primUpdates = new Dictionary<string,List<SceneObjectGroup>>();
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<SceneObjectGroup>(m_primUpdates.Values); lock (m_primUpdateLocks[bucketName])
//presenceUpdates = new List<ScenePresence>(m_presenceUpdates.Values); {
m_primUpdates.Clear(); updated = true;
//m_presenceUpdates.Clear(); primUpdates.Add(bucketName, new List<SceneObjectGroup>(m_primUpdates[bucketName].Values));
m_primUpdates[bucketName].Clear();
}
} }
} }
/*
List<ScenePresence> presenceUpdates = null;
if (m_presenceUpdates.Count > 0) if (m_presenceUpdates.Count > 0)
{ {
lock (m_updateScenePresenceLock) lock (m_updateScenePresenceLock)
@ -372,8 +368,9 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
m_presenceUpdates.Clear(); m_presenceUpdates.Clear();
} }
} }
* */
if (primUpdates != null || presenceUpdates != null) if (updated)
{ {
long timeStamp = DateTime.Now.Ticks; 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 // 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 // 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 foreach (SceneObjectGroup sog in primUpdates[bucketName])
sog.UpdateTaintedBucketSyncInfo(timeStamp);
if (m_isSyncRelay || (!sog.IsDeleted && CheckObjectForSendingUpdate(sog)))
{ {
//send /*
string sogxml = SceneObjectSerializer.ToXml2Format(sog); //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
SymmetricSyncMessage syncMsg = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.UpdatedObject, sogxml); sog.UpdateTaintedBucketSyncInfo(timeStamp);
SendObjectUpdateToRelevantSyncConnectors(sog, syncMsg); 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);
} }
} }
} }

View File

@ -29,6 +29,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
Terrain, Terrain,
NewObject, // objects NewObject, // objects
UpdatedObject, // objects UpdatedObject, // objects
UpdatedBucketProperties, //object properties in one bucket
RemovedObject, // objects RemovedObject, // objects
LinkObject, LinkObject,
DelinkObject, DelinkObject,

View File

@ -68,6 +68,7 @@ namespace OpenSim.Region.Framework.Interfaces
//Enqueue updates for scene-objects and scene-presences //Enqueue updates for scene-objects and scene-presences
void QueueSceneObjectPartForUpdate(SceneObjectPart part); void QueueSceneObjectPartForUpdate(SceneObjectPart part);
void QueueScenePresenceForTerseUpdate(ScenePresence presence); 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 //The folloiwng calls deal with object updates, and will insert each update into an outgoing queue of each SyncConnector
void SendSceneUpdates(); void SendSceneUpdates();

View File

@ -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 #endregion
} }
} }

View File

@ -4957,6 +4957,7 @@ namespace OpenSim.Region.Framework.Scenes
//lock for concurrent updates of the timestamp and actorID. //lock for concurrent updates of the timestamp and actorID.
private Object m_updateLock = new Object(); private Object m_updateLock = new Object();
private string m_bucketName; private string m_bucketName;
private bool m_bucketTainted = false;
public long LastUpdateTimeStamp public long LastUpdateTimeStamp
{ {
@ -4975,6 +4976,11 @@ namespace OpenSim.Region.Framework.Scenes
get { return m_bucketName; } get { return m_bucketName; }
} }
public bool Tainted
{
get { return m_bucketTainted; }
}
public BucketSyncInfo(string bucketName) public BucketSyncInfo(string bucketName)
{ {
m_bucketName = bucketName; m_bucketName = bucketName;
@ -4987,15 +4993,23 @@ namespace OpenSim.Region.Framework.Scenes
m_bucketName = bucketName; m_bucketName = bucketName;
} }
public void UpdateSyncInfo(long timeStamp, string actorID) public void UpdateSyncInfoAndClearTaint(long timeStamp, string actorID)
{ {
lock (m_updateLock) lock (m_updateLock)
{ {
m_lastUpdateTimeStamp = timeStamp; m_lastUpdateTimeStamp = timeStamp;
m_lastUpdateActorID = actorID; 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()); m_bucketUpdateLocks.Add(bucketName, new Object());
} }
/*
if (!m_bucketSyncTainted.ContainsKey(bucketName)) if (!m_bucketSyncTainted.ContainsKey(bucketName))
{ {
m_bucketSyncTainted.Add(bucketName, false); m_bucketSyncTainted.Add(bucketName, false);
} }
* */
} }
if (!m_BucketUpdateProcessorRegistered) if (!m_BucketUpdateProcessorRegistered)
@ -5488,22 +5504,18 @@ namespace OpenSim.Region.Framework.Scenes
if (m_syncEnabled && m_bucketSyncTainted.Count > 0) if (m_syncEnabled && m_bucketSyncTainted.Count > 0)
{ {
string bucketName = m_primPropertyBucketMap[property]; 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; return m_bucketSyncInfoList[bucketName].Tainted;
foreach (KeyValuePair<string, bool> pair in m_bucketSyncTainted)
{
updatedLocally = pair.Value;
if (updatedLocally)
break;
}
return updatedLocally;
} }
/* /*
public void ClearBucketTaint() public void ClearBucketTaint()
{ {
@ -5530,16 +5542,19 @@ namespace OpenSim.Region.Framework.Scenes
string bucketName = pair.Key; string bucketName = pair.Key;
if (m_bucketSyncTainted[bucketName]) if (m_bucketSyncTainted[bucketName])
{ {
m_bucketSyncInfoList[bucketName].UpdateSyncInfo(timeStamp, m_localActorID); m_bucketSyncInfoList[bucketName].UpdateSyncInfoAndClearTaint(timeStamp, m_localActorID);
m_bucketSyncTainted[bucketName] = false; //m_bucketSyncTainted[bucketName] = false;
} }
} }
} }
} }
/// <summary> /// <summary>
/// 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.
/// </summary> /// </summary>
/// <param name="timeStamp">the timestamp value to be set for any updated bucket</param>
public void UpdateTaintedBucketSyncInfo(long timeStamp) public void UpdateTaintedBucketSyncInfo(long timeStamp)
{ {
if (m_syncEnabled) if (m_syncEnabled)
@ -5549,13 +5564,24 @@ namespace OpenSim.Region.Framework.Scenes
string bucketName = pair.Key; string bucketName = pair.Key;
if (m_bucketSyncTainted[bucketName]) if (m_bucketSyncTainted[bucketName])
{ {
m_bucketSyncInfoList[bucketName].UpdateSyncInfo(timeStamp, m_localActorID); m_bucketSyncInfoList[bucketName].UpdateSyncInfoAndClearTaint(timeStamp, m_localActorID);
m_bucketSyncTainted[bucketName] = false;
} }
} }
} }
} }
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;
}
}
}
/// <summary> /// <summary>
/// Update the timestamp and actorID information of the bucket the given property belongs to. /// Update the timestamp and actorID information of the bucket the given property belongs to.
/// </summary> /// </summary>
@ -5569,7 +5595,7 @@ namespace OpenSim.Region.Framework.Scenes
long timeStamp = DateTime.Now.Ticks; long timeStamp = DateTime.Now.Ticks;
if (m_bucketSyncInfoList.ContainsKey(bucketName)) if (m_bucketSyncInfoList.ContainsKey(bucketName))
{ {
m_bucketSyncInfoList[bucketName].UpdateSyncInfo(timeStamp, m_localActorID); m_bucketSyncInfoList[bucketName].UpdateSyncInfoAndClearTaint(timeStamp, m_localActorID);
} }
else else
{ {
@ -5586,7 +5612,7 @@ namespace OpenSim.Region.Framework.Scenes
{ {
string bucketName = pair.Key; string bucketName = pair.Key;
BucketSyncInfo syncInfo= pair.Value; BucketSyncInfo syncInfo= pair.Value;
syncInfo.UpdateSyncInfo(timeStamp, m_localActorID); syncInfo.UpdateSyncInfoAndClearTaint(timeStamp, m_localActorID);
m_bucketSyncTainted[bucketName] = false; m_bucketSyncTainted[bucketName] = false;
} }
} }