Added functions to sync on RemoveObject event. Object can now be removed from either script-engine

or Scene and can be synced.
Problem: there is significant delay form when an object is removed on one actor, to the time it also
disappears from the viewer attaching to the other actor.
dsg
Huaiyu (Kitty) Liu 2010-12-28 14:54:40 -08:00
parent 384895cbdd
commit 130915f669
3 changed files with 138 additions and 15 deletions

View File

@ -20,6 +20,7 @@ using System.Threading;
using System.Text;
using Mono.Addins;
using OpenMetaverse.StructuredData;
/////////////////////////////////////////////////////////////////////////////////////////////
//KittyL: created 12/17/2010, to start DSG Symmetric Synch implementation
@ -87,6 +88,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
//Register for the OnPostSceneCreation event
m_scene.EventManager.OnPostSceneCreation += OnPostSceneCreation;
m_scene.EventManager.OnObjectBeingRemovedFromScene += new EventManager.ObjectBeingRemovedFromScene(RegionSyncModule_OnObjectBeingRemovedFromScene);
}
//Called after AddRegion() has been called for all region modules of the scene
@ -229,18 +231,12 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
foreach (SceneObjectGroup sog in primUpdates)
{
//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
if (m_isSyncRelay || CheckObjectForSendingUpdate(sog))
if (m_isSyncRelay || (!sog.IsDeleted && CheckObjectForSendingUpdate(sog)))
{
//send
List<SyncConnector> syncConnectors = GetSyncConnectorsForObjectUpdates(sog);
foreach (SyncConnector connector in syncConnectors)
{
string sogxml = SceneObjectSerializer.ToXml2Format(sog);
SymmetricSyncMessage syncMsg = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.UpdatedObject, sogxml);
connector.EnqueueOutgoingUpdate(sog.UUID, syncMsg.ToBytes());
}
string sogxml = SceneObjectSerializer.ToXml2Format(sog);
SymmetricSyncMessage syncMsg = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.UpdatedObject, sogxml);
SendObjectUpdateToRelevantSyncConnectors(sog, syncMsg);
}
}
/*
@ -294,6 +290,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
}
#endregion //IRegionSyncModule
#region ICommandableModule Members
@ -394,6 +391,18 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
m_log.Warn("[REGION SYNC MODULE]: StatsTimerElapsed -- NOT yet implemented.");
}
private void SendObjectUpdateToRelevantSyncConnectors(SceneObjectGroup sog, SymmetricSyncMessage syncMsg)
{
List<SyncConnector> syncConnectors = GetSyncConnectorsForObjectUpdates(sog);
foreach (SyncConnector connector in syncConnectors)
{
//string sogxml = SceneObjectSerializer.ToXml2Format(sog);
//SymmetricSyncMessage syncMsg = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.UpdatedObject, sogxml);
connector.EnqueueOutgoingUpdate(sog.UUID, syncMsg.ToBytes());
}
}
/// <summary>
/// Check if we need to send out an update message for the given object.
/// </summary>
@ -401,9 +410,6 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
/// <returns></returns>
private bool CheckObjectForSendingUpdate(SceneObjectGroup sog)
{
if (sog == null || sog.IsDeleted)
return false;
//If any part in the object has the last update caused by this actor itself, then send the update
foreach (SceneObjectPart part in sog.Parts)
{
@ -742,6 +748,11 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
//HandleAddNewObject(sog);
return;
}
case SymmetricSyncMessage.MsgType.RemovedObject:
{
HandleRemovedObject(msg);
return;
}
default:
return;
}
@ -780,6 +791,49 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
}
}
private void HandleRemovedObject(SymmetricSyncMessage msg)
{
// Get the data from message and error check
OSDMap data = DeserializeMessage(msg);
if (data == null)
{
SymmetricSyncMessage.HandleError(LogHeader, msg, "Could not deserialize JSON data.");
return;
}
// Get the parameters from data
//ulong regionHandle = data["regionHandle"].AsULong();
//uint localID = data["UUID"].AsUInteger();
UUID sogUUID = data["UUID"].AsUUID();
SceneObjectGroup sog = m_scene.SceneGraph.GetGroupByPrim(sogUUID);
if (sog != null)
{
m_scene.DeleteSceneObjectBySynchronization(sog);
}
}
HashSet<string> exceptions = new HashSet<string>();
private OSDMap DeserializeMessage(SymmetricSyncMessage msg)
{
OSDMap data = null;
try
{
data = OSDParser.DeserializeJson(Encoding.ASCII.GetString(msg.Data, 0, msg.Length)) as OSDMap;
}
catch (Exception e)
{
lock (exceptions)
// If this is a new message, then print the underlying data that caused it
if (!exceptions.Contains(e.Message))
m_log.Error(LogHeader + " " + Encoding.ASCII.GetString(msg.Data, 0, msg.Length));
data = null;
}
return data;
}
private void HandleAddNewObject(SceneObjectGroup sog)
{
//RegionSyncModule only add object to SceneGraph. Any actor specific actions will be implemented
@ -793,6 +847,27 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
}
/// <summary>
/// Send a sync message to remove the given objects in all connected actors, if this is a relay node.
/// UUID is used for identified a removed object.
/// </summary>
/// <param name="sog"></param>
private void RegionSyncModule_OnObjectBeingRemovedFromScene(SceneObjectGroup sog)
{
//Only send the message out if this is a relay node for sync messages, or this actor caused deleting the object
if (m_isSyncRelay || CheckObjectForSendingUpdate(sog))
{
OSDMap data = new OSDMap(1);
//data["regionHandle"] = OSD.FromULong(regionHandle);
//data["localID"] = OSD.FromUInteger(sog.LocalId);
data["UUID"] = OSD.FromUUID(sog.UUID);
SymmetricSyncMessage rsm = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.RemovedObject, OSDParser.SerializeJsonString(data));
SendObjectUpdateToRelevantSyncConnectors(sog, rsm);
}
}
#endregion //RegionSyncModule members and functions

View File

@ -620,6 +620,45 @@ namespace OpenSim.Region.Framework.Scenes
return m_sceneGraph.AddOrUpdateObjectBySynchronization(sog);
}
//Similar to DeleteSceneObject, except that this does not change LastUpdateActorID and LastUpdateTimeStamp
public void DeleteSceneObjectBySynchronization(SceneObjectGroup group)
{
// m_log.DebugFormat("[SCENE]: Deleting scene object {0} {1}", group.Name, group.UUID);
//SceneObjectPart rootPart = group.GetChildPart(group.UUID);
// Serialise calls to RemoveScriptInstances to avoid
// deadlocking on m_parts inside SceneObjectGroup
lock (m_deleting_scene_object)
{
group.RemoveScriptInstances(true);
}
SceneObjectPart[] partList = group.Parts;
foreach (SceneObjectPart part in partList)
{
if (part.IsJoint() && ((part.Flags & PrimFlags.Physics) != 0))
{
PhysicsScene.RequestJointDeletion(part.Name); // FIXME: what if the name changed?
}
else if (part.PhysActor != null)
{
PhysicsScene.RemovePrim(part.PhysActor);
part.PhysActor = null;
}
}
if (UnlinkSceneObject(group, false))
{
EventManager.TriggerObjectBeingRemovedFromScene(group);
EventManager.TriggerParcelPrimCountTainted();
}
bool silent = false; //do not suppress broadcasting changes to other clients, for debugging with viewers
group.DeleteGroupFromScene(silent);
}
#endregion //SYMMETRIC SYNC
@ -2364,6 +2403,15 @@ namespace OpenSim.Region.Framework.Scenes
group.DeleteGroupFromScene(silent);
// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID);
//SYMMETRIC SYNC
//Set the ActorID and TimeStamp info for this latest update
foreach (SceneObjectPart part in group.Parts)
{
part.SyncInfoUpdate();
}
//end of SYMMETRIC SYNC
}
/// <summary>

View File

@ -4952,7 +4952,7 @@ namespace OpenSim.Region.Framework.Scenes
}
}
private void SyncInfoUpdate()
public void SyncInfoUpdate()
{
//Trick: calling UpdateTimestamp here makes sure that when an object was received and de-serialized, before
// its parts are linked together, neither TimeStamp or ActorID will be modified. This is because during de-serialization,