Checked in Functions that encode/decode sync messages based on object/prim properties.

These functions will convert the GroupPosition or Postiion properties into/out of the encoding.
	NewObjectMessageEncoder
	GeneralBucketPropertiesEncoder
	PhysicsBucketPropertiesEncoder
	NewObjectMessageDecoder
	GeneralBucketPropertiesDecoder
	PhysicsBucketPropertiesDecoder

Also checked some changes to SendXXXToRelevantSyncConnectors functions.
dsg
Huaiyu (Kitty) Liu 2011-03-29 14:55:21 -07:00
parent eed53e8a56
commit 5b79e15285
1 changed files with 476 additions and 61 deletions

View File

@ -254,7 +254,7 @@ 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()
{ {
if (!IsSyncingWithOtherActors()) if (!IsSyncingWithOtherSyncNodes())
{ {
//no SyncConnector connected. clear update queues and return. //no SyncConnector connected. clear update queues and return.
foreach (string bucketName in m_propertyBucketNames) foreach (string bucketName in m_propertyBucketNames)
@ -395,7 +395,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
public void SendTerrainUpdates(long updateTimeStamp, string lastUpdateActorID) public void SendTerrainUpdates(long updateTimeStamp, string lastUpdateActorID)
{ {
if (!IsSyncingWithOtherActors()) if (!IsSyncingWithOtherSyncNodes())
{ {
//no SyncConnector connected. Do nothing. //no SyncConnector connected. Do nothing.
return; return;
@ -414,19 +414,19 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
/// <param name="sog"></param> /// <param name="sog"></param>
public void SendNewObject(SceneObjectGroup sog) public void SendNewObject(SceneObjectGroup sog)
{ {
if (!IsSyncingWithOtherActors()) if (!IsSyncingWithOtherSyncNodes())
{ {
//no SyncConnector connected. Do nothing. //no SyncConnector connected. Do nothing.
return; return;
} }
//First, make sure the linked group has updated timestamp info for synchronization
sog.BucketSyncInfoUpdate(); sog.BucketSyncInfoUpdate();
SymmetricSyncMessage rsm = CreateNewObjectMessage(sog); SymmetricSyncMessage rsm = NewObjectMessageEncoder(sog);
//SendObjectUpdateToRelevantSyncConnectors(sog, rsm); //SendObjectUpdateToRelevantSyncConnectors(sog, rsm);
SendSceneEventToRelevantSyncConnectors(m_actorID, rsm, sog); //SendSceneEventToRelevantSyncConnectors(m_actorID, rsm, sog);
SendSpecialObjectUpdateToRelevantSyncConnectors(m_actorID, sog, rsm);
} }
/// <summary> /// <summary>
@ -438,7 +438,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
//private void RegionSyncModule_OnObjectBeingRemovedFromScene(SceneObjectGroup sog) //private void RegionSyncModule_OnObjectBeingRemovedFromScene(SceneObjectGroup sog)
public void SendDeleteObject(SceneObjectGroup sog, bool softDelete) public void SendDeleteObject(SceneObjectGroup sog, bool softDelete)
{ {
if (!IsSyncingWithOtherActors()) if (!IsSyncingWithOtherSyncNodes())
{ {
//no SyncConnector connected. Do nothing. //no SyncConnector connected. Do nothing.
return; return;
@ -467,7 +467,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
{ {
if(children.Count==0) return; if(children.Count==0) return;
if (!IsSyncingWithOtherActors()) if (!IsSyncingWithOtherSyncNodes())
{ {
//no SyncConnector connected. Do nothing. //no SyncConnector connected. Do nothing.
return; return;
@ -500,7 +500,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
{ {
if (prims.Count==0 || beforeDelinkGroups.Count==0) return; if (prims.Count==0 || beforeDelinkGroups.Count==0) return;
if (!IsSyncingWithOtherActors()) if (!IsSyncingWithOtherSyncNodes())
{ {
//no SyncConnector connected. Do nothing. //no SyncConnector connected. Do nothing.
return; return;
@ -544,12 +544,12 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
} }
SymmetricSyncMessage rsm = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.DelinkObject, OSDParser.SerializeJsonString(data)); SymmetricSyncMessage rsm = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.DelinkObject, OSDParser.SerializeJsonString(data));
SendDelinkObjectToRelevantSyncConnectors(beforeDelinkGroups, rsm); SendDelinkObjectToRelevantSyncConnectors(m_actorID, beforeDelinkGroups, rsm);
} }
public void PublishSceneEvent(EventManager.EventNames ev, Object[] evArgs) public void PublishSceneEvent(EventManager.EventNames ev, Object[] evArgs)
{ {
if (!IsSyncingWithOtherActors()) if (!IsSyncingWithOtherSyncNodes())
{ {
//no SyncConnector connected. Do nothing. //no SyncConnector connected. Do nothing.
return; return;
@ -748,19 +748,21 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
private delegate void PrimUpdatePerBucketSender(string bucketName, List<SceneObjectPart> primUpdates); private delegate void PrimUpdatePerBucketSender(string bucketName, List<SceneObjectPart> primUpdates);
private Dictionary<string, PrimUpdatePerBucketSender> m_primUpdatesPerBucketSender = new Dictionary<string, PrimUpdatePerBucketSender>(); private Dictionary<string, PrimUpdatePerBucketSender> m_primUpdatesPerBucketSender = new Dictionary<string, PrimUpdatePerBucketSender>();
/* private delegate void PrimUpdatePerBucketReceiver(string bucketName, OSDMap data);
private Dictionary<string, PrimUpdatePerBucketReceiver> m_primUpdatesPerBucketReceiver = new Dictionary<string, PrimUpdatePerBucketReceiver>();
//The functions that encode properties in each bucket. For now, //The functions that encode properties in each bucket. For now,
//general bucket works on SOG, physics bucket works on SOP, so we define //general bucket works on SOG, physics bucket works on SOP, so we define
//the arg to be of type Object to be general in the interface. //the arg to be of type Object to be general in the interface.
//TO DO: redesign the interface once the bucket encoders working on more //TO DO: redesign the interface once the bucket encoders working on more
//consistent/specific arguments. //consistent/specific arguments.
private delegate string UpdatePerBucketEncoder(string bucketName, Object arg); private delegate OSDMap UpdatePerBucketEncoder(string bucketName, Object arg);
private Dictionary<string, UpdatePerBucketEncoder> m_updatePerBucketEncoder = new Dictionary<string, UpdatePerBucketEncoder>(); private Dictionary<string, UpdatePerBucketEncoder> m_updatePerBucketEncoder = new Dictionary<string, UpdatePerBucketEncoder>();
//Decoders of properties in each bucket //Decoders of properties in each bucket
private delegate void UpdatePerBucketDecoder(string bucketName, string encoding, out Object outData); private delegate void UpdatePerBucketDecoder(string bucketName, OSDMap data, out Object outData);
private Dictionary<string, UpdatePerBucketDecoder> m_updatePerBucketDecoder = new Dictionary<string, UpdatePerBucketDecoder>(); private Dictionary<string, UpdatePerBucketDecoder> m_updatePerBucketDecoder = new Dictionary<string, UpdatePerBucketDecoder>();
* */
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>();
@ -828,6 +830,142 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
SceneObjectPart.InitializePropertyBucketInfo(m_primPropertyBucketMap, m_propertyBucketNames, m_actorID); SceneObjectPart.InitializePropertyBucketInfo(m_primPropertyBucketMap, m_propertyBucketNames, m_actorID);
} }
#region Bucket specific sender/receiver, encoder/decoder
////////////////////////////////////////////////////////////////////////
// These are bucket specific functions, hence are "hard-coded", that is,
// they each undestand the particular bucket it operates for.
//
// Each encoder should encode properties in OSDMap, and besides
// properties, encode two more items:
// Bucket -- bucket's name,
// GroupPostiion -- the object group or object part's group position,
// which is used to identify which quark an object
// group/part belongs to.
// The encoder needs to convert positions from local to global coordinates,
// if necessary (client manager needs to).
//
// Each receiver should check if the object/prim's group position is
// within local sync quarks' space. If not, ignore the sync message.
// Otherwise, it calls decoder to decode the properties.
//
// Each decoder need to convert the coordicates if necessary (only client
// manager needs to register for the conversion handler).
////////////////////////////////////////////////////////////////////////
/// <summary>
/// Decode and construct SceneObjectGroup, convert the coordinates of Position
/// properties if necessary (from global to local).
/// </summary>
/// <param name="sogxml"></param>
/// <param name="inLocalQuarks">indicates if the constructed SOG resides in the Sync Quarks</param>
/// <returns></returns>
// private SceneObjectGroup DecodeSceneObjectGroup(string sogxml, out bool inLocalQuarks)
private SceneObjectGroup DecodeSceneObjectGroup(string sogxml)
{
SceneObjectGroup sog = SceneObjectSerializer.FromXml2Format(sogxml);
return sog;
}
/// <summary>
/// Encode all properties of an object. Assumption: no matter how many
/// buckets are designed, there is always a "General" bucket that contains
/// non-actor specific properties.
/// The encoding include the sogxml of the object as serialized by
/// SceneObjectSerializer, and encoding of properties in all buckets other
/// than "General" bucket.
/// </summary>
/// <param name="sog"></param>
/// <returns></returns>
private SymmetricSyncMessage NewObjectMessageEncoder(SceneObjectGroup sog)
{
OSDMap data = new OSDMap();
string sogxml = SceneObjectSerializer.ToXml2Format(sog);
data["SogXml"] = OSD.FromString(sogxml);
//convert the coordinates if necessary
Vector3 globalPos = sog.AbsolutePosition;
/*
if (CoordinatesConversionHandler != null)
{
bool inComingMsg = false;
globalPos = CoordinatesConversionHandler(globalPos, inComingMsg);
}
* */
data["GroupPosition"] = OSDMap.FromVector3(globalPos);
foreach (string bucketName in m_propertyBucketNames)
{
//We assume there is always a General bucket, and properties in it
//are covered in the xml serialization above
if (bucketName.Equals(m_generalBucketName))
continue;
OSDArray partArray = new OSDArray();
foreach (SceneObjectPart part in sog.Parts)
{
OSDMap partData = m_updatePerBucketEncoder[bucketName](bucketName, (Object)part);
partArray.Add(partData);
}
data[bucketName] = partArray;
}
//string sogxml = SceneObjectSerializer.ToXml2Format(sog);
SymmetricSyncMessage rsm = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.NewObject, OSDParser.SerializeJsonString(data));
m_log.DebugFormat("{0}: Created a NewObject message for {1},{2}, at pos {3}", LogHeader, sog.Name, sog.UUID, globalPos);
return rsm;
}
private void NewObjectMessageDecoder(OSDMap data, out Object group)
{
//First, create the object group and add it to Scene
string sogxml = data["SogXml"].AsString();
Vector3 globalPos = data["GroupPosition"].AsVector3();
SceneObjectGroup sog = DecodeSceneObjectGroup(sogxml);
//Convert the coordinates if necessary
Vector3 localPos = globalPos;
/*
if (CoordinatesConversionHandler != null)
{
bool inComingMsg = true;
localPos = CoordinatesConversionHandler(globalPos, inComingMsg);
}
* */
sog.AbsolutePosition = localPos;
//TEMP DEBUG
m_log.DebugFormat("{0}: received NewObject sync message for object {1}, {2} at pos {3}", LogHeader, sog.Name, sog.UUID, sog.AbsolutePosition.ToString());
Scene.ObjectUpdateResult updateResult = m_scene.AddNewSceneObjectBySync(sog);
//Second, for each prim in the object, update the properties in buckets
//other than the General bucket
foreach (string bucketName in m_propertyBucketNames)
{
if (bucketName.Equals(m_generalBucketName))
continue;
if (!data.ContainsKey(bucketName))
{
m_log.WarnFormat("{0}: On receiving NewObject, no properties in bucket {1} are included", LogHeader, bucketName);
continue;
}
OSDArray partDataArray = (OSDArray)data[bucketName];
for (int i = 0; i < partDataArray.Count; i++)
{
OSDMap partData = (OSDMap)partDataArray[i];
m_primUpdatesPerBucketReceiver[bucketName](bucketName, partData);
}
}
group = (Object)sog;
}
//As of current version, we still use the xml serialization as most of SOP's properties are in the General bucket. //As of current version, we still use the xml serialization as most of SOP's properties are in the General bucket.
//Going forward, we may serialize the properties differently, e.g. using OSDMap //Going forward, we may serialize the properties differently, e.g. using OSDMap
private void PrimUpdatesGeneralBucketSender(string bucketName, List<SceneObjectPart> primUpdates) private void PrimUpdatesGeneralBucketSender(string bucketName, List<SceneObjectPart> primUpdates)
@ -835,20 +973,22 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
Dictionary<UUID, SceneObjectGroup> updatedObjects = new Dictionary<UUID, SceneObjectGroup>(); Dictionary<UUID, SceneObjectGroup> updatedObjects = new Dictionary<UUID, SceneObjectGroup>();
foreach (SceneObjectPart part in primUpdates) foreach (SceneObjectPart part in primUpdates)
{ {
if(!part.ParentGroup.IsDeleted) if (!part.ParentGroup.IsDeleted)
updatedObjects[part.ParentGroup.UUID] = part.ParentGroup; updatedObjects[part.ParentGroup.UUID] = part.ParentGroup;
} }
long timeStamp = DateTime.Now.Ticks; long timeStamp = DateTime.Now.Ticks;
foreach (SceneObjectGroup sog in updatedObjects.Values) foreach (SceneObjectGroup sog in updatedObjects.Values)
{ {
sog.UpdateTaintedBucketSyncInfo(bucketName, timeStamp); //this update the timestamp and clear the taint info of the bucket sog.UpdateTaintedBucketSyncInfo(bucketName, timeStamp); //this update the timestamp and clear the taint info of the bucket
string sogGeneralBucketEncoding = SceneObjectSerializer.ToXml2Format(sog); //string sogGeneralBucketEncoding = SceneObjectSerializer.ToXml2Format(sog);
//string sogGeneralBucketEncoding = GeneralBucketPropertiesEncoder(bucketName, sog, null); //SymmetricSyncMessage syncMsg = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.UpdatedObject, sogGeneralBucketEncoding);
SymmetricSyncMessage syncMsg = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.UpdatedObject, sogGeneralBucketEncoding);
OSDMap data = GeneralBucketPropertiesEncoder(bucketName, sog);
SymmetricSyncMessage syncMsg = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.UpdatedObject, OSDParser.SerializeJsonString(data));
lock (m_stats) m_statSOGBucketOut++; lock (m_stats) m_statSOGBucketOut++;
//m_log.DebugFormat(LogHeader + " calling SendObjectUpdateToRelevantSyncConnectors for general bucket for sog {0},{1}", sog.Name, sog.UUID); m_log.DebugFormat(LogHeader + " calling SendObjectUpdateToRelevantSyncConnectors for general bucket for sog {0},{1}", sog.Name, sog.UUID);
SendObjectUpdateToRelevantSyncConnectors(sog, syncMsg); SendObjectUpdateToRelevantSyncConnectors(sog, syncMsg);
@ -862,24 +1002,144 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
//UpdateBucektLastSentTime(bucketName, timeStamp); //UpdateBucektLastSentTime(bucketName, timeStamp);
} }
private string GeneralBucketPropertiesEncoder(string bucketName, Object sog) private void PrimUpdatesGeneralBucketReceiver(string bucketName, OSDMap data)
{ {
if (sog is SceneObjectGroup) lock (m_stats) m_statSOGBucketIn++;
if (!data.ContainsKey("GroupPosition"))
{ {
SceneObjectGroup group = (SceneObjectGroup)sog; m_log.WarnFormat("{0}: PrimUpdatesGeneralBucketReceiver -- no GroupPosition is provided in the received update message");
return SceneObjectSerializer.ToXml2Format(group); return;
}
//Check the object/prim's position, if outside of local quarks, ignore the update.
Vector3 groupPosition = data["GroupPosition"].AsVector3();
/*
if (!m_syncQuarkManager.IsPosInSyncQuarks(groupPosition))
{
m_log.WarnFormat("{0}: Received a {1} bucket update for object at pos {2}, OUT OF local quarks", LogHeader, bucketName, groupPosition.ToString());
return;
}
* */
m_log.DebugFormat("{0}: PrimUpdatesGeneralBucketReceiver called, for update at GroupPosition {1}", LogHeader, groupPosition.ToString());
Object ret;
GeneralBucketPropertiesDecoder(bucketName, data, out ret);
SceneObjectGroup sog;
if (ret is SceneObjectGroup && ret != null)
{
sog = (SceneObjectGroup)ret;
} }
else else
return String.Empty; {
m_log.DebugFormat("{0}: Error in GeneralBucketPropertiesDecoder.", LogHeader);
return;
}
if (sog.IsDeleted)
{
m_log.DebugFormat("{0}: Ignoring update on deleted object, Name: {1}, UUID: {2}.", LogHeader, sog.Name, sog.UUID);
return;
}
else
{
m_log.DebugFormat("{0}: UpdateObjectBySynchronization to be called for: sog {1}, {2}, at post {3}", LogHeader, sog.Name, sog.UUID, sog.AbsolutePosition);
Scene.ObjectUpdateResult updateResult = m_scene.UpdateObjectBySynchronization(sog);
switch (updateResult)
{
case Scene.ObjectUpdateResult.New:
m_log.DebugFormat("[{0} Object \"{1}\" ({1}) ({2}) added.", LogHeader, sog.Name, sog.UUID.ToString(), sog.LocalId.ToString());
break;
case Scene.ObjectUpdateResult.Updated:
m_log.DebugFormat("[{0} Object \"{1}\" ({1}) ({2}) updated.", LogHeader, sog.Name, sog.UUID.ToString(), sog.LocalId.ToString());
break;
case Scene.ObjectUpdateResult.Error:
m_log.WarnFormat("[{0} Object \"{1}\" ({1}) ({2}) -- add or update ERROR.", LogHeader, sog.Name, sog.UUID.ToString(), sog.LocalId.ToString());
break;
case Scene.ObjectUpdateResult.Unchanged:
//m_log.DebugFormat("[{0} Object \"{1}\" ({1}) ({2}) unchanged after receiving an update.", LogHeader, sog.Name, sog.UUID.ToString(), sog.LocalId.ToString());
break;
}
m_log.DebugFormat("{0}: end of processing UpdatedObject {4} bucket, for object {1}, {2}, at pos {3}", LogHeader, sog.Name,
sog.UUID, sog.AbsolutePosition, bucketName);
}
} }
private void GeneralBucketPropertiesDecoder(string bucketName, string encoding, out Object sog)
/// <summary>
/// Encode the properties of a given object(group) into string, to be
/// included in an outgoing sync message.
/// </summary>
/// <param name="bucketName"></param>
/// <param name="sog"></param>
/// <returns></returns>
private OSDMap GeneralBucketPropertiesEncoder(string bucketName, Object group)
{ {
SceneObjectGroup group = SceneObjectSerializer.FromXml2Format(encoding); OSDMap data = new OSDMap();
sog = (Object)group;
SceneObjectGroup sog;
if (group is SceneObjectGroup)
{
sog = (SceneObjectGroup)group;
}
else
return data;
string sogxml = SceneObjectSerializer.ToXml2Format(sog);
data["Bucket"] = OSDMap.FromString(bucketName);
data["SogXml"] = OSDMap.FromString(sogxml);
//convert the coordinates if necessary
Vector3 globalPos = sog.AbsolutePosition;
/*
if (CoordinatesConversionHandler != null)
{
bool inComingMsg = false;
globalPos = CoordinatesConversionHandler(globalPos, inComingMsg);
}
* */
data["GroupPosition"] = OSDMap.FromVector3(globalPos);
//TEMP DEBUG
m_log.Debug(LogHeader + " GeneralBucketPropertiesEncoder for " + sog.Name + "," + sog.UUID + ". GlobalPos: " + globalPos.ToString());
return data;
} }
private void GeneralBucketPropertiesDecoder(string bucketName, OSDMap data, out Object group)
{
group = null;
if (!data.ContainsKey("SogXml") || !data.ContainsKey("GroupPosition"))
{
m_log.WarnFormat("{0}: GeneralBucketPropertiesDecoder -- Either SogXml or GroupPosition is missing in the received update message");
return;
}
string sogxml = data["SogXml"].AsString();
Vector3 globalPos = data["GroupPosition"].AsVector3();
SceneObjectGroup sog = SceneObjectSerializer.FromXml2Format(sogxml);
/*
if (CoordinatesConversionHandler != null)
{
bool inComingMsg = true;
sog.AbsolutePosition = CoordinatesConversionHandler(globalPos, inComingMsg);
}
* */
group = sog;
}
private void PrimUpdatesPhysicsBucketSender(string bucketName, List<SceneObjectPart> primUpdates) private void PrimUpdatesPhysicsBucketSender(string bucketName, List<SceneObjectPart> primUpdates)
{ {
foreach (SceneObjectPart updatedPart in primUpdates) foreach (SceneObjectPart updatedPart in primUpdates)
@ -891,11 +1151,11 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
//string partPhysicsBucketEncoding = PhysicsBucketPropertiesEncoder(bucketName, updatedPart); //string partPhysicsBucketEncoding = PhysicsBucketPropertiesEncoder(bucketName, updatedPart);
OSDMap partData = PhysicsBucketPropertiesEncoder(bucketName, updatedPart); OSDMap partData = PhysicsBucketPropertiesEncoder(bucketName, updatedPart);
SymmetricSyncMessage syncMsg = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.UpdatedBucketProperties, OSDParser.SerializeJsonString(partData)); //SymmetricSyncMessage syncMsg = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.UpdatedBucketProperties, OSDParser.SerializeJsonString(partData));
//m_log.DebugFormat("{0}: PhysBucketSender for {1}, pos={2}", LogHeader, updatedPart.UUID.ToString(), pa.Position.ToString()); SymmetricSyncMessage syncMsg = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.UpdatedObject, OSDParser.SerializeJsonString(partData));
lock (m_stats) m_statPhysBucketOut++; lock (m_stats) m_statPhysBucketOut++;
SendObjectUpdateToRelevantSyncConnectors(updatedPart, syncMsg); SendPrimUpdateToRelevantSyncConnectors(updatedPart, syncMsg, updatedPart.BucketSyncInfoList[bucketName].LastUpdateActorID);
//clear the taints //clear the taints
updatedPart.BucketSyncInfoList[bucketName].ClearBucketTaintBySync(); updatedPart.BucketSyncInfoList[bucketName].ClearBucketTaintBySync();
@ -904,15 +1164,84 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
//UpdateBucektLastSentTime(bucketName); //UpdateBucektLastSentTime(bucketName);
} }
private OSDMap PhysicsBucketPropertiesEncoder(string bucketName, SceneObjectPart updatedPart) private void PrimUpdatesPhysicsBucketReceiver(string bucketName, OSDMap data)
{
lock (m_stats) m_statPhysBucketIn++;
if (!data.ContainsKey("GroupPosition"))
{
m_log.WarnFormat("{0}: PrimUpdatesGeneralBucketReceiver -- no GroupPosition is provided in the received update message");
return;
}
//check the object/prim's position, if outside of local quarks, ignore it
Vector3 groupPosition = data["GroupPosition"].AsVector3();
/*
if (!m_syncQuarkManager.IsPosInSyncQuarks(groupPosition))
{
m_log.WarnFormat("{0}: Received a {1} bucket update for object at pos {2}, OUT OF local quarks", LogHeader, bucketName, groupPosition.ToString());
return;
}
* */
m_log.DebugFormat("{0}: PrimUpdatesPhysicsBucketReceiver called, for update at GroupPosition {1}", LogHeader, groupPosition.ToString());
Object ret;
PhysicsBucketPropertiesDecoder(bucketName, data, out ret);
OSDMap recvData;
if (ret is OSDMap && ret != null)
{
recvData = (OSDMap)ret;
}
else
{
m_log.DebugFormat("{0}: Error in PhysicsBucketPropertiesDecoder.", LogHeader);
return;
}
UUID partUUID = data["UUID"].AsUUID();
BucketSyncInfo rBucketSyncInfo = new BucketSyncInfo(bucketName);
rBucketSyncInfo.LastUpdateTimeStamp = data["LastUpdateTimeStamp"].AsLong();
rBucketSyncInfo.LastUpdateActorID = data["LastUpdateActorID"].AsString();
m_scene.UpdateObjectPartBucketProperties(bucketName, partUUID, data, rBucketSyncInfo);
//TEMP DEBUG
SceneObjectPart localPart = m_scene.GetSceneObjectPart(partUUID);
m_log.DebugFormat("{0}: end of processing UpdatedObject {4} bucket, for part {1}, {2}, at group pos {3}", LogHeader, localPart.Name,
localPart.UUID, localPart.GroupPosition, bucketName);
}
private OSDMap PhysicsBucketPropertiesEncoder(string bucketName, Object part)
{ {
OSDMap data = new OSDMap(); OSDMap data = new OSDMap();
data["UUID"] = OSD.FromUUID(updatedPart.UUID); SceneObjectPart updatedPart;
//data["UUID"] = OSD.FromUUID(pa.UUID); if (part is SceneObjectPart)
{
updatedPart = (SceneObjectPart)part;
}
else
return data;
data["Bucket"] = OSD.FromString(bucketName); data["Bucket"] = OSD.FromString(bucketName);
data["GroupPosition"] = OSD.FromVector3(updatedPart.GroupPosition); //Convert GroupPosition if necessary
Vector3 globalGroupPos = updatedPart.GroupPosition;
/*
if (CoordinatesConversionHandler != null)
{
bool inComingMsg = false;
globalGroupPos = CoordinatesConversionHandler(globalGroupPos, inComingMsg);
}
* */
data["GroupPosition"] = OSDMap.FromVector3(globalGroupPos); //This records the global GroupPosition.
data["UUID"] = OSD.FromUUID(updatedPart.UUID);
data["OffsetPosition"] = OSD.FromVector3(updatedPart.OffsetPosition); data["OffsetPosition"] = OSD.FromVector3(updatedPart.OffsetPosition);
data["Scale"] = OSD.FromVector3(updatedPart.Scale); data["Scale"] = OSD.FromVector3(updatedPart.Scale);
data["AngularVelocity"] = OSD.FromVector3(updatedPart.AngularVelocity); data["AngularVelocity"] = OSD.FromVector3(updatedPart.AngularVelocity);
@ -922,8 +1251,20 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
if (pa != null) if (pa != null)
{ {
//Convert Position if necessary
Vector3 globalPos = pa.Position;
/*
if (CoordinatesConversionHandler != null)
{
bool inComingMsg = false;
globalPos = CoordinatesConversionHandler(globalPos, inComingMsg);
}
data["Position"] = OSDMap.FromVector3(globalPos); //This records the global GroupPosition.
* */
data["Size"] = OSD.FromVector3(pa.Size); data["Size"] = OSD.FromVector3(pa.Size);
data["Position"] = OSD.FromVector3(pa.Position); //data["Position"] = OSD.FromVector3(pa.Position);
data["Force"] = OSD.FromVector3(pa.Force); data["Force"] = OSD.FromVector3(pa.Force);
data["Velocity"] = OSD.FromVector3(pa.Velocity); data["Velocity"] = OSD.FromVector3(pa.Velocity);
data["RotationalVelocity"] = OSD.FromVector3(pa.RotationalVelocity); data["RotationalVelocity"] = OSD.FromVector3(pa.RotationalVelocity);
@ -943,17 +1284,38 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
data["LastUpdateTimeStamp"] = OSD.FromLong(updatedPart.BucketSyncInfoList[bucketName].LastUpdateTimeStamp); data["LastUpdateTimeStamp"] = OSD.FromLong(updatedPart.BucketSyncInfoList[bucketName].LastUpdateTimeStamp);
data["LastUpdateActorID"] = OSD.FromString(updatedPart.BucketSyncInfoList[bucketName].LastUpdateActorID); data["LastUpdateActorID"] = OSD.FromString(updatedPart.BucketSyncInfoList[bucketName].LastUpdateActorID);
//m_log.Debug(LogHeader + " Send out Physics Bucket updates for " + updatedPart.Name + ","+updatedPart.UUID+ ". GroupPosition: " + updatedPart.GroupPosition.ToString());
return data; return data;
} }
private void PhysicsBucketPropertiesDecoder(string bucketName, SymmetricSyncMessage msg, out Object sog) private void PhysicsBucketPropertiesDecoder(string bucketName, OSDMap msgData, out Object data)
{ {
OSDMap data = DeserializeMessage(msg); /*
sog = (Object)data; if (msgData.ContainsKey("GroupPosition"))
{
if (CoordinatesConversionHandler != null)
{
bool inComingMsg = true;
Vector3 globalGroupPos = msgData["GroupPosition"].AsVector3();
msgData["GroupPosition"] = OSDMap.FromVector3(CoordinatesConversionHandler(globalGroupPos, inComingMsg));
}
}
if (msgData.ContainsKey("Position"))
{
if (CoordinatesConversionHandler != null)
{
bool inComingMsg = true;
Vector3 globalPos = msgData["Position"].AsVector3();
msgData["Position"] = OSDMap.FromVector3(CoordinatesConversionHandler(globalPos, inComingMsg));
}
}
* */
data = (Object)msgData;
} }
#endregion //Bucket specific sender/receiver, encoder/decoder
private bool HaveUpdatesToSendoutForSync(SceneObjectPart part, string bucketName) private bool HaveUpdatesToSendoutForSync(SceneObjectPart part, string bucketName)
{ {
if (m_isSyncRelay) if (m_isSyncRelay)
@ -992,17 +1354,20 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
m_propertyBucketNames.Add(m_physicsBucketName); m_propertyBucketNames.Add(m_physicsBucketName);
m_maxNumOfPropertyBuckets = m_propertyBucketNames.Count; m_maxNumOfPropertyBuckets = m_propertyBucketNames.Count;
//Linking each bucket with the sender function that serializes the properties in the bucket and send out sync message //Linking each bucket with the sender/receiver function for sending/receiving an update message
m_primUpdatesPerBucketSender.Add(m_generalBucketName, PrimUpdatesGeneralBucketSender); m_primUpdatesPerBucketSender.Add(m_generalBucketName, PrimUpdatesGeneralBucketSender);
m_primUpdatesPerBucketSender.Add(m_physicsBucketName, PrimUpdatesPhysicsBucketSender); m_primUpdatesPerBucketSender.Add(m_physicsBucketName, PrimUpdatesPhysicsBucketSender);
/* m_primUpdatesPerBucketReceiver.Add(m_generalBucketName, PrimUpdatesGeneralBucketReceiver);
m_updatePerBucketEncoder.Add(generalBucketName, GeneralBucketPropertiesEncoder); m_primUpdatesPerBucketReceiver.Add(m_physicsBucketName, PrimUpdatesPhysicsBucketReceiver);
m_updatePerBucketEncoder.Add(physicsBucketName, PhysicsBucketPropertiesEncoder);
//Linking each bucket with the encoder/decoder functions that encode/decode the properties in the bucket
m_updatePerBucketEncoder.Add(m_generalBucketName, GeneralBucketPropertiesEncoder);
m_updatePerBucketEncoder.Add(m_physicsBucketName, PhysicsBucketPropertiesEncoder);
m_updatePerBucketDecoder.Add(m_generalBucketName, GeneralBucketPropertiesDecoder);
m_updatePerBucketDecoder.Add(m_physicsBucketName, PhysicsBucketPropertiesDecoder);
m_updatePerBucketDecoder.Add(generalBucketName, GeneralBucketPropertiesDecoder);
m_updatePerBucketDecoder.Add(physicsBucketName, PhysicsBucketPropertiesDecoder);
* */
//m_lastUpdateSentTime.Add("General", 0); //m_lastUpdateSentTime.Add("General", 0);
//m_lastUpdateSentTime.Add("Physics", 0); //m_lastUpdateSentTime.Add("Physics", 0);
@ -1048,7 +1413,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
} }
} }
private bool IsSyncingWithOtherActors() private bool IsSyncingWithOtherSyncNodes()
{ {
return (m_syncConnectors.Count > 0); return (m_syncConnectors.Count > 0);
} }
@ -1068,13 +1433,10 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
//Object updates are sent by enqueuing into each connector's outQueue. //Object updates are sent by enqueuing into each connector's outQueue.
private void SendObjectUpdateToRelevantSyncConnectors(SceneObjectGroup sog, SymmetricSyncMessage syncMsg) private void SendObjectUpdateToRelevantSyncConnectors(SceneObjectGroup sog, SymmetricSyncMessage syncMsg)
{ {
List<SyncConnector> syncConnectors = GetSyncConnectorsForObjectUpdates(sog); HashSet<SyncConnector> syncConnectors = GetSyncConnectorsForObjectUpdates(sog);
foreach (SyncConnector connector in syncConnectors) foreach (SyncConnector connector in syncConnectors)
{ {
//string sogxml = SceneObjectSerializer.ToXml2Format(sog);
//SymmetricSyncMessage syncMsg = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.UpdatedObject, sogxml);
//m_log.Debug("Send " + syncMsg.Type.ToString() + " about sog "+sog.Name+","+sog.UUID+ " at pos "+sog.AbsolutePosition.ToString()+" to " + connector.OtherSideActorID); //m_log.Debug("Send " + syncMsg.Type.ToString() + " about sog "+sog.Name+","+sog.UUID+ " at pos "+sog.AbsolutePosition.ToString()+" to " + connector.OtherSideActorID);
connector.EnqueueOutgoingUpdate(sog.UUID, syncMsg.ToBytes()); connector.EnqueueOutgoingUpdate(sog.UUID, syncMsg.ToBytes());
@ -1084,7 +1446,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
//Object updates are sent by enqueuing into each connector's outQueue. //Object updates are sent by enqueuing into each connector's outQueue.
private void SendObjectUpdateToRelevantSyncConnectors(SceneObjectPart updatedPart, SymmetricSyncMessage syncMsg) private void SendObjectUpdateToRelevantSyncConnectors(SceneObjectPart updatedPart, SymmetricSyncMessage syncMsg)
{ {
List<SyncConnector> syncConnectors = GetSyncConnectorsForObjectUpdates(updatedPart); HashSet<SyncConnector> syncConnectors = GetSyncConnectorsForObjectUpdates(updatedPart);
foreach (SyncConnector connector in syncConnectors) foreach (SyncConnector connector in syncConnectors)
{ {
@ -1098,16 +1460,36 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
} }
} }
private void SendDelinkObjectToRelevantSyncConnectors(List<SceneObjectGroup> beforeDelinkGroups, SymmetricSyncMessage syncMsg) //Object updates are sent by enqueuing into each connector's outQueue.
private void SendPrimUpdateToRelevantSyncConnectors(SceneObjectPart updatedPart, SymmetricSyncMessage syncMsg, string lastUpdateActorID)
{
HashSet<SyncConnector> syncConnectors = GetSyncConnectorsForPrimUpdates(updatedPart);
foreach (SyncConnector connector in syncConnectors)
{
//string sogxml = SceneObjectSerializer.ToXml2Format(sog);
//SymmetricSyncMessage syncMsg = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.UpdatedObject, sogxml);
//m_log.Debug("Send " + syncMsg.Type.ToString() + " about sop " + updatedPart.Name + "," + updatedPart.UUID + " at pos "+updatedPart.GroupPosition.ToString()
//+" to " + connector.OtherSideActorID);
if (!connector.OtherSideActorID.Equals(lastUpdateActorID))
{
connector.EnqueueOutgoingUpdate(updatedPart.UUID, syncMsg.ToBytes());
}
}
}
private void SendDelinkObjectToRelevantSyncConnectors(string senderActorID, List<SceneObjectGroup> beforeDelinkGroups, SymmetricSyncMessage syncMsg)
{ {
HashSet<int> syncConnectorsSent = new HashSet<int>(); HashSet<int> syncConnectorsSent = new HashSet<int>();
foreach (SceneObjectGroup sog in beforeDelinkGroups) foreach (SceneObjectGroup sog in beforeDelinkGroups)
{ {
List<SyncConnector> syncConnectors = GetSyncConnectorsForObjectUpdates(sog); HashSet<SyncConnector> syncConnectors = GetSyncConnectorsForObjectUpdates(sog);
foreach (SyncConnector connector in syncConnectors) foreach (SyncConnector connector in syncConnectors)
{ {
if (!syncConnectorsSent.Contains(connector.ConnectorNum)) if (!syncConnectorsSent.Contains(connector.ConnectorNum) && !connector.OtherSideActorID.Equals(senderActorID))
{ {
m_log.DebugFormat("{0}: send DeLinkObject to {1}", LogHeader, connector.Description); m_log.DebugFormat("{0}: send DeLinkObject to {1}", LogHeader, connector.Description);
connector.EnqueueOutgoingUpdate(sog.UUID, syncMsg.ToBytes()); connector.EnqueueOutgoingUpdate(sog.UUID, syncMsg.ToBytes());
@ -1117,6 +1499,24 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
} }
} }
/// <summary>
/// Send some special object updatess to other sync nodes, including:
/// NewObject, RemoveObject, LinkObject. The sync messages are sent out right
/// away, without being enqueue'ed as UpdatedObject messages.
/// </summary>
/// <param name="sog"></param>
/// <param name="syncMsg"></param>
private void SendSpecialObjectUpdateToRelevantSyncConnectors(string init_actorID, SceneObjectGroup sog, SymmetricSyncMessage syncMsg)
{
HashSet<SyncConnector> syncConnectors = GetSyncConnectorsForObjectUpdates(sog);
foreach (SyncConnector connector in syncConnectors)
{
if (!connector.OtherSideActorID.Equals(init_actorID))
connector.Send(syncMsg);
}
}
//Events are send out right away, without being put into the connector's outQueue first. //Events are send out right away, without being put into the connector's outQueue first.
//May need a better method for managing the outgoing messages (i.e. prioritizing object updates and events) //May need a better method for managing the outgoing messages (i.e. prioritizing object updates and events)
private void SendSceneEventToRelevantSyncConnectors(string init_actorID, SymmetricSyncMessage rsm, SceneObjectGroup sog) private void SendSceneEventToRelevantSyncConnectors(string init_actorID, SymmetricSyncMessage rsm, SceneObjectGroup sog)
@ -1165,9 +1565,9 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
/// </summary> /// </summary>
/// <param name="sog"></param> /// <param name="sog"></param>
/// <returns></returns> /// <returns></returns>
private List<SyncConnector> GetSyncConnectorsForObjectUpdates(SceneObjectGroup sog) private HashSet<SyncConnector> GetSyncConnectorsForObjectUpdates(SceneObjectGroup sog)
{ {
List<SyncConnector> syncConnectors = new List<SyncConnector>(); HashSet<SyncConnector> syncConnectors = new HashSet<SyncConnector>();
if (m_isSyncRelay) if (m_isSyncRelay)
{ {
//This is a relay node in the synchronization overlay, forward it to all connectors. //This is a relay node in the synchronization overlay, forward it to all connectors.
@ -1193,11 +1593,26 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
return syncConnectors; return syncConnectors;
} }
private List<SyncConnector> GetSyncConnectorsForObjectUpdates(SceneObjectPart updatedPart) private HashSet<SyncConnector> GetSyncConnectorsForObjectUpdates(SceneObjectPart updatedPart)
{ {
return GetSyncConnectorsForObjectUpdates(updatedPart.ParentGroup); return GetSyncConnectorsForObjectUpdates(updatedPart.ParentGroup);
} }
private HashSet<SyncConnector> GetSyncConnectorsForPrimUpdates(SceneObjectPart updatedPart)
{
/*
Vector3 globalPos = updatedPart.GroupPosition;
if (CoordinatesConversionHandler != null)
{
bool inComingMsg = false; //this function should only be triggered by trying to send messages out
globalPos = CoordinatesConversionHandler(globalPos, inComingMsg);
}
return m_syncConnectorManager.GetSyncConnectorsByPosition(globalPos);
* */
HashSet<SyncConnector> syncConnectors = new HashSet<SyncConnector>(GetSyncConnectorsForObjectUpdates(updatedPart.ParentGroup));
return syncConnectors;
}
/// <summary> /// <summary>
/// Get the set of SyncConnectors to send certain scene events. /// Get the set of SyncConnectors to send certain scene events.
/// </summary> /// </summary>