Added RegionSyncModule.ProcessAndEnqueuePrimUpdatesBySync, and revised functions relavant

to processing and forwarding prim updates. Code good for 2 CM and PSA to sync on NewObject
and UpdatedPrimProperties.
dsg
Huaiyu (Kitty) Liu 2011-04-18 15:54:24 -07:00
parent 8b08e4b176
commit 28f401d95a
4 changed files with 152 additions and 48 deletions

View File

@ -569,6 +569,8 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
OSDMap encodedSOG = SceneObjectEncoder(sog); OSDMap encodedSOG = SceneObjectEncoder(sog);
SymmetricSyncMessage syncMsg = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.NewObject, OSDParser.SerializeJsonString(encodedSOG)); SymmetricSyncMessage syncMsg = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.NewObject, OSDParser.SerializeJsonString(encodedSOG));
m_log.DebugFormat("{0}: Send NewObject out for {1},{2}", LogHeader, sog.Name, sog.UUID);
SendSpecialObjectUpdateToRelevantSyncConnectors(m_actorID, sog, syncMsg); SendSpecialObjectUpdateToRelevantSyncConnectors(m_actorID, sog, syncMsg);
} }
@ -2269,14 +2271,36 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
{ {
OSDMap data = DeserializeMessage(msg); OSDMap data = DeserializeMessage(msg);
UUID primUUID; UUID primUUID;
List<PropertySyncInfo> propertiesSyncInfo; HashSet<PropertySyncInfo> propertiesSyncInfo;
m_primSyncInfoManager.DecodePrimProperties(data, out primUUID, out propertiesSyncInfo);
if (!data.ContainsKey("primUUID"))
{
m_log.WarnFormat("{0}: HandleUpdatedPrimProperties -- primUUID is missing in {1}", LogHeader, msg.Type.ToString());
return;
}
primUUID = data["primUUID"].AsUUID();
SceneObjectPart sop = m_scene.GetSceneObjectPart(primUUID); SceneObjectPart sop = m_scene.GetSceneObjectPart(primUUID);
if (sop != null && !sop.ParentGroup.IsDeleted && propertiesSyncInfo.Count>0) if (sop == null || sop.ParentGroup.IsDeleted)
{ {
m_primSyncInfoManager.UpdatePrimSyncInfoBySync(sop, propertiesSyncInfo); m_log.WarnFormat("{0}: HandleUpdatedPrimProperties -- prim {1} no longer in local SceneGraph", LogHeader, primUUID);
return;
}
propertiesSyncInfo = m_primSyncInfoManager.DecodePrimProperties(data);
if (propertiesSyncInfo.Count>0)
{
List<SceneObjectPartSyncProperties> propertiesUpdated = m_primSyncInfoManager.UpdatePrimSyncInfoBySync(sop, propertiesSyncInfo);
if (propertiesUpdated.Count > 0)
{
//Enqueue the updated SOP and its properties for sync
ProcessAndEnqueuePrimUpdatesBySync(sop, propertiesUpdated);
//Calling SOP.ScheduleFullUpdate(), so that viewers, if any,
//will receive updates as well.
sop.ScheduleFullUpdate(null);
}
} }
} }
@ -3163,7 +3187,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
private PrimSyncInfoManager m_primSyncInfoManager; private PrimSyncInfoManager m_primSyncInfoManager;
//private //private
/// <summary> /// <summary>
/// Triggered when some properties in an SOP have been updated. /// Triggered when some properties in an SOP have been updated locally.
/// Sync the properties' values in this sync module with those in /// Sync the properties' values in this sync module with those in
/// SOP, and update timestamp accordingly. /// SOP, and update timestamp accordingly.
/// </summary> /// </summary>
@ -3171,6 +3195,9 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
/// <param name="updatedProperties"></param> /// <param name="updatedProperties"></param>
public void ProcessAndEnqueuePrimUpdatesByLocal(SceneObjectPart part, List<SceneObjectPartSyncProperties> updatedProperties) public void ProcessAndEnqueuePrimUpdatesByLocal(SceneObjectPart part, List<SceneObjectPartSyncProperties> updatedProperties)
{ {
if (part.ParentGroup == null || part.ParentGroup.IsDeleted)
return;
//Sync values with SOP's data and update timestamp according, to //Sync values with SOP's data and update timestamp according, to
//obtain the list of properties that really have been updated //obtain the list of properties that really have been updated
//and should be propogated to other sync nodes. //and should be propogated to other sync nodes.
@ -3199,6 +3226,49 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
} }
} }
/// <summary>
/// Triggered when some properties of the given SOP have been updated by
/// receiving a sync message UpdatedPrimProperties.
/// </summary>
/// <param name="part"></param>
/// <param name="updatedProperties"></param>
public void ProcessAndEnqueuePrimUpdatesBySync(SceneObjectPart part, List<SceneObjectPartSyncProperties> updatedProperties)
{
if (part.ParentGroup == null || part.ParentGroup.IsDeleted)
return;
HashSet<SceneObjectPartSyncProperties> propertiesToSync = new HashSet<SceneObjectPartSyncProperties>();
if (m_isSyncRelay)
{
//If this is a sync relay node, it needs to forward out the updates
propertiesToSync = new HashSet<SceneObjectPartSyncProperties>(updatedProperties);
}
//Enqueue the prim with the set of updated properties
if (propertiesToSync.Count > 0)
{
lock (m_primPropertyUpdateLock)
{
if (m_primPropertyUpdates.ContainsKey(part.UUID))
{
foreach (SceneObjectPartSyncProperties property in propertiesToSync)
{
//Include the "property" into the list of updated properties.
//HashSet's Add function should handle it correctly whether the property
//is or is not in the set.
m_primPropertyUpdates[part.UUID].Add(property);
}
}
else
{
m_primPropertyUpdates.Add(part.UUID, propertiesToSync);
}
}
}
}
/// <summary> /// <summary>
/// Triggered periodically to send out sync messages that include /// Triggered periodically to send out sync messages that include
/// prim-properties that have been updated since last SyncOut. /// prim-properties that have been updated since last SyncOut.
@ -4474,6 +4544,8 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
return propertiesToBeSynced; return propertiesToBeSynced;
} }
//pre-process properties in updatedProperties, for sanity checking
//or expanding/shrinking
foreach (SceneObjectPartSyncProperties property in updatedProperties) foreach (SceneObjectPartSyncProperties property in updatedProperties)
{ {
//first, see if there are physics properties updated but PhysActor //first, see if there are physics properties updated but PhysActor
@ -4507,9 +4579,10 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
return propertiesToBeSynced; return propertiesToBeSynced;
} }
//Second, for each updated property in the list, compare the value //Second, for each updated property in the list, find out the ones
//maintained here and the value in SOP. If different, update the //that really have recently been updated by local operations
//value here and set the timestamp and syncID HashSet<SceneObjectPartSyncProperties> propertiesUpdatedByLocal = new HashSet<SceneObjectPartSyncProperties>();
lock (m_primSyncInfoLock) lock (m_primSyncInfoLock)
{ {
foreach (SceneObjectPartSyncProperties property in propertiesToBeSynced) foreach (SceneObjectPartSyncProperties property in propertiesToBeSynced)
@ -4531,17 +4604,19 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
if (updated) if (updated)
{ {
propertiesToBeSynced.Add(property); propertiesUpdatedByLocal.Add(property);
} }
} }
} }
return propertiesToBeSynced; return propertiesUpdatedByLocal;
} }
//TODO: might return status such as Updated, Unchanged, etc to caller //TODO: might return status such as Updated, Unchanged, etc to caller
public void UpdatePropertiesBySync(SceneObjectPart part, List<PropertySyncInfo> propertiesSyncInfo) public List<SceneObjectPartSyncProperties> UpdatePropertiesBySync(SceneObjectPart part, HashSet<PropertySyncInfo> propertiesSyncInfo)
{ {
long recvTS = DateTime.Now.Ticks; long recvTS = DateTime.Now.Ticks;
List<SceneObjectPartSyncProperties> propertiesUpdated = new List<SceneObjectPartSyncProperties>();
foreach (PropertySyncInfo pSyncInfo in propertiesSyncInfo) foreach (PropertySyncInfo pSyncInfo in propertiesSyncInfo)
{ {
bool updated = false; bool updated = false;
@ -4562,10 +4637,11 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
{ {
//UpdateSOPProperty(part, m_propertiesSyncInfo[property]); //UpdateSOPProperty(part, m_propertiesSyncInfo[property]);
SetSOPPropertyValue(part, property); SetSOPPropertyValue(part, property);
propertiesUpdated.Add(property);
} }
} }
} }
return propertiesUpdated;
} }
/// <summary> /// <summary>
@ -4601,30 +4677,27 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
} }
/// <summary> /// <summary>
/// Decode PropertySyncInfo for each property and insert into m_propertiesSyncInfo. /// Decode a set of PropertySyncInfo from OSDMap.
/// This is called to initialize this PrimSyncInfo by decoding from OSDMap.
/// </summary> /// </summary>
/// <param name="primSyncInfoData"></param> /// <param name="primSyncInfoData"></param>
public void DecodeAndSetProperiesSyncInfo(OSDMap primSyncInfoData) public static HashSet<PropertySyncInfo> DecodeProperiesSyncInfo(OSDMap primSyncInfoData)
{ {
foreach (SceneObjectPartSyncProperties property in FullSetPrimProperties) HashSet<PropertySyncInfo> propertiesSyncInfo = new HashSet<PropertySyncInfo>();
foreach (string propertyString in primSyncInfoData.Keys)
{ {
if (primSyncInfoData.ContainsKey(property.ToString())) //convert string to enum
SceneObjectPartSyncProperties property = (SceneObjectPartSyncProperties)Enum.Parse(typeof(SceneObjectPartSyncProperties), propertyString, true);
if (FullSetPrimProperties.Contains(property))
{ {
//PropertySyncInfo propertySyncInfo = OSDMapToPropertySyncInfo((OSDMap)primSyncInfoData[property.ToString()]); //PropertySyncInfo propertySyncInfo = OSDMapToPropertySyncInfo((OSDMap)primSyncInfoData[property.ToString()]);
PropertySyncInfo propertySyncInfo = new PropertySyncInfo(property, (OSDMap)primSyncInfoData[property.ToString()]); PropertySyncInfo propertySyncInfo = new PropertySyncInfo(property, (OSDMap)primSyncInfoData[propertyString]);
if (!m_propertiesSyncInfo.ContainsKey(property)) propertiesSyncInfo.Add(propertySyncInfo);
{
m_propertiesSyncInfo.Add(property, propertySyncInfo);
}
else
{
m_propertiesSyncInfo[property] = propertySyncInfo;
}
}else{ }else{
m_log.WarnFormat("DecodeAndSetProperiesSyncInfo: Property {0} not included in the given OSDMap", property); //m_log.WarnFormat("DecodeAndSetProperiesSyncInfo: Property {0} not a valid SceneObjectPartSyncProperties", propertyString);
} }
} }
return propertiesSyncInfo;
} }
//TO BE FINISHED //TO BE FINISHED
@ -4689,7 +4762,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
} }
else else
{ {
m_log.WarnFormat("DecodeAndSetProperiesSyncInfo: Property {0} not included in the given OSDMap", property); m_log.WarnFormat("InitPropertiesSyncInfoFromOSDMap: Property {0} not included in the given OSDMap", property);
} }
} }
} }
@ -4703,15 +4776,18 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
case SceneObjectPartSyncProperties.Shape: case SceneObjectPartSyncProperties.Shape:
string primShapeString = PropertySerializer.SerializeShape(part); string primShapeString = PropertySerializer.SerializeShape(part);
string primShapeStringHash = Util.Md5Hash(primShapeString); string primShapeStringHash = Util.Md5Hash(primShapeString);
//primShapeString.GetHashCode
if (!m_propertiesSyncInfo[property].IsHashValueEqual(primShapeStringHash)) if (!m_propertiesSyncInfo[property].IsHashValueEqual(primShapeStringHash))
{ {
//The SOP's property value has a newer timestamp, update the data in
//PrimSyncInfoManager to be consistent; otherwise, overwrite SOP's property
//value by copying that from PrimSyncInfoManager
if (lastUpdateTS > m_propertiesSyncInfo[property].LastUpdateTimeStamp) if (lastUpdateTS > m_propertiesSyncInfo[property].LastUpdateTimeStamp)
{ {
UpdatePropertySyncInfoByLocal(property, lastUpdateTS, syncID, (Object)primShapeString, primShapeStringHash); UpdatePropertySyncInfoByLocal(property, lastUpdateTS, syncID, (Object)primShapeString, primShapeStringHash);
updated = true; updated = true;
} }
else if (lastUpdateTS > m_propertiesSyncInfo[property].LastUpdateTimeStamp) else if (lastUpdateTS < m_propertiesSyncInfo[property].LastUpdateTimeStamp)
{ {
PrimitiveBaseShape shape = PropertySerializer.DeSerializeShape((string)m_propertiesSyncInfo[property].LastUpdateValue); PrimitiveBaseShape shape = PropertySerializer.DeSerializeShape((string)m_propertiesSyncInfo[property].LastUpdateValue);
part.Shape = shape; part.Shape = shape;
@ -4729,7 +4805,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
UpdatePropertySyncInfoByLocal(property, lastUpdateTS, syncID, (Object)primTaskInventoryString, primTaskInventoryStringHash); UpdatePropertySyncInfoByLocal(property, lastUpdateTS, syncID, (Object)primTaskInventoryString, primTaskInventoryStringHash);
updated = true; updated = true;
} }
else if (lastUpdateTS > m_propertiesSyncInfo[property].LastUpdateTimeStamp) else if (lastUpdateTS < m_propertiesSyncInfo[property].LastUpdateTimeStamp)
{ {
TaskInventoryDictionary taskInv = PropertySerializer.DeSerializeTaskInventory((string)m_propertiesSyncInfo[property].LastUpdateValue); TaskInventoryDictionary taskInv = PropertySerializer.DeSerializeTaskInventory((string)m_propertiesSyncInfo[property].LastUpdateValue);
part.TaskInventory = taskInv; part.TaskInventory = taskInv;
@ -5191,11 +5267,16 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
} }
break; break;
case SceneObjectPartSyncProperties.MediaUrl: case SceneObjectPartSyncProperties.MediaUrl:
if (!part.MediaUrl.Equals(m_propertiesSyncInfo[property].LastUpdateValue)) //Use "!=" to compare, instead of "Equals", because part.MediaUrl
//might be null.
//String assignment in C# create a new copy of the string, hence we do
//not call clone() explicitly, so that the case of "part.MediaUrl==null"
//can be handled properly as well
if (part.MediaUrl != (string) m_propertiesSyncInfo[property].LastUpdateValue)
{ {
if (lastUpdateByLocalTS > m_propertiesSyncInfo[property].LastUpdateTimeStamp) if (lastUpdateByLocalTS > m_propertiesSyncInfo[property].LastUpdateTimeStamp)
{ {
m_propertiesSyncInfo[property].UpdateSyncInfoByLocal(lastUpdateByLocalTS, syncID, (Object)part.MediaUrl.Clone()); m_propertiesSyncInfo[property].UpdateSyncInfoByLocal(lastUpdateByLocalTS, syncID, (Object)part.MediaUrl);
propertyUpdatedByLocal = true; propertyUpdatedByLocal = true;
} }
else if (lastUpdateByLocalTS < m_propertiesSyncInfo[property].LastUpdateTimeStamp) else if (lastUpdateByLocalTS < m_propertiesSyncInfo[property].LastUpdateTimeStamp)
@ -5994,6 +6075,12 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
return pValue; return pValue;
} }
/// <summary>
/// Set the property's value based on the value maintained in PrimSyncInfoManager.
/// Assumption: caller will call ScheduleFullUpdate to enqueue updates properly.
/// </summary>
/// <param name="part"></param>
/// <param name="property"></param>
private void SetSOPPropertyValue(SceneObjectPart part, SceneObjectPartSyncProperties property) private void SetSOPPropertyValue(SceneObjectPart part, SceneObjectPartSyncProperties property)
{ {
if (part == null) return; if (part == null) return;
@ -6251,6 +6338,8 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
break; break;
} }
//Calling ScheduleFullUpdate to trigger enqueuing updates for sync'ing (relay sync nodes need to do so)
//part.ScheduleFullUpdate(new List<SceneObjectPartSyncProperties>() { property });
} }
} }
@ -6326,17 +6415,18 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
} }
} }
public void UpdatePrimSyncInfoBySync(SceneObjectPart part, List<PropertySyncInfo> propertiesSyncInfo) public List<SceneObjectPartSyncProperties> UpdatePrimSyncInfoBySync(SceneObjectPart part, HashSet<PropertySyncInfo> propertiesSyncInfo)
{ {
if (m_primsInSync.ContainsKey(part.UUID)) if (m_primsInSync.ContainsKey(part.UUID))
{ {
PrimSyncInfo primSyncInfo = m_primsInSync[part.UUID]; PrimSyncInfo primSyncInfo = m_primsInSync[part.UUID];
primSyncInfo.UpdatePropertiesBySync(part, propertiesSyncInfo); return primSyncInfo.UpdatePropertiesBySync(part, propertiesSyncInfo);
} }
else else
{ {
//This should not happen, as we should only receive UpdatedPrimProperties after receiving a NewObject message //This should not happen, as we should only receive UpdatedPrimProperties after receiving a NewObject message
m_log.WarnFormat("PrimSyncInfoManager.UpdatePrimSyncInfoBySync: SOP {0},{1} not in local record of PrimSyncInfo.", part.Name, part.UUID); m_log.WarnFormat("PrimSyncInfoManager.UpdatePrimSyncInfoBySync: SOP {0},{1} not in local record of PrimSyncInfo.", part.Name, part.UUID);
return new List<SceneObjectPartSyncProperties>();
} }
} }
@ -6366,18 +6456,22 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
return data; return data;
} }
public void DecodePrimProperties(OSDMap primPropertiesData, out UUID primUUID, out List<PropertySyncInfo> propertiesSyncInfo) public HashSet<PropertySyncInfo> DecodePrimProperties(OSDMap primPropertiesData)
{ {
primUUID = UUID.Zero; HashSet<PropertySyncInfo> propertiesSyncInfo = new HashSet<PropertySyncInfo>();
propertiesSyncInfo = new List<PropertySyncInfo>(); if (!primPropertiesData.ContainsKey("propertyData"))
if (!primPropertiesData.ContainsKey("primUUID") || !primPropertiesData.ContainsKey("propertyData"))
{ {
m_log.WarnFormat("DecodePrimProperties: either primUUID or propertyData is missing"); m_log.WarnFormat("DecodePrimProperties: propertyData is missing");
return propertiesSyncInfo;
} }
else
{ //if(!m_primsInSync.ContainsKey(primUUID)){
// m_log.WarnFormat("prim {0} not in PrimSyncInfoManager's record");
// return;
//}
propertiesSyncInfo = PrimSyncInfo.DecodeProperiesSyncInfo((OSDMap)primPropertiesData["propertyData"]);
} return propertiesSyncInfo;
} }
public PrimSyncInfo DecodeFullSetPrimProperties(OSDMap primData) public PrimSyncInfo DecodeFullSetPrimProperties(OSDMap primData)

View File

@ -71,6 +71,7 @@ namespace OpenSim.Region.Framework.Interfaces
//void QueueSceneObjectPartForUpdate(SceneObjectPart part); //void QueueSceneObjectPartForUpdate(SceneObjectPart part);
void QueueScenePresenceForTerseUpdate(ScenePresence presence); void QueueScenePresenceForTerseUpdate(ScenePresence presence);
//void ProcessAndEnqueuePrimUpdatesBySync(SceneObjectPart part, List<SceneObjectPartSyncProperties> updatedProperties);
void ProcessAndEnqueuePrimUpdatesByLocal(SceneObjectPart part, List<SceneObjectPartSyncProperties> updatedProperties); void ProcessAndEnqueuePrimUpdatesByLocal(SceneObjectPart part, List<SceneObjectPartSyncProperties> updatedProperties);
void SyncOutPrimUpdates(); void SyncOutPrimUpdates();

View File

@ -2169,9 +2169,13 @@ namespace OpenSim.Region.Framework.Scenes
sceneObject.RootPart.SetParentLocalId(avatar.LocalId); sceneObject.RootPart.SetParentLocalId(avatar.LocalId);
} }
//SYMMETRIC SYNC, //DSG SYNC,
sceneObject.HasGroupChanged = true;
//NewObject is sent via a specific sync message, not through updates;
//hence not passing any property list here in calling
//ScheduleGroupForFullUpdate().
sceneObject.ScheduleGroupForFullUpdate_SyncInfoUnchanged(); sceneObject.ScheduleGroupForFullUpdate_SyncInfoUnchanged();
//end of SYMMETRIC SYNC, //end of DSG SYNC,
Entities.Add(sceneObject); Entities.Add(sceneObject);

View File

@ -3204,7 +3204,7 @@ namespace OpenSim.Region.Framework.Scenes
//SYMMETRIC SYNC //SYMMETRIC SYNC
//KittyL: 04/06/2011, No longer calling QueueSceneObjectPartForUpdate //KittyL: 04/06/2011, No longer calling QueueSceneObjectPartForUpdate
//from here. Local updates are now recorded by calling IRegionSyncModule.RecordPrimUpdatesByLocal(). //from here. Local updates are now recorded by calling IRegionSyncModule.ProcessAndEnqueuePrimUpdatesByLocal().
/* /*
if (m_parentGroup.Scene.RegionSyncModule != null) if (m_parentGroup.Scene.RegionSyncModule != null)
{ {
@ -6070,13 +6070,13 @@ namespace OpenSim.Region.Framework.Scenes
{ {
if (updatedProperties != null && updatedProperties.Count > 0) if (updatedProperties != null && updatedProperties.Count > 0)
{ {
if (m_parentGroup != null && m_parentGroup.Scene.RegionSyncModule != null) if (m_parentGroup != null && m_parentGroup.Scene!=null && m_parentGroup.Scene.RegionSyncModule != null)
{ {
m_parentGroup.Scene.RegionSyncModule.ProcessAndEnqueuePrimUpdatesByLocal(this, updatedProperties); m_parentGroup.Scene.RegionSyncModule.ProcessAndEnqueuePrimUpdatesByLocal(this, updatedProperties);
} }
} }
base.ScheduleTerseUpdate(updatedProperties); base.ScheduleFullUpdate(updatedProperties);
} }
public override void ScheduleTerseUpdate(List<SceneObjectPartSyncProperties> updatedProperties) public override void ScheduleTerseUpdate(List<SceneObjectPartSyncProperties> updatedProperties)
@ -6135,6 +6135,11 @@ namespace OpenSim.Region.Framework.Scenes
{ {
base.PhysicsCollision(e); base.PhysicsCollision(e);
} }
///////////////////////////////////////////////////////////////////////
//Per property sync functions
///////////////////////////////////////////////////////////////////////
} }
//end of SYMMETRIC SYNC //end of SYMMETRIC SYNC