diff --git a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs index 2fbac6481a..1db8ac6379 100644 --- a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs +++ b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs @@ -379,6 +379,44 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule SendObjectUpdateToRelevantSyncConnectors(linkedGroup, rsm); } + public void SendDeLinkObject(List prims, List beforeDelinkGroups, List afterDelinkGroups) + { + if (prims.Count==0 || beforeDelinkGroups.Count==0) return; + + OSDMap data = new OSDMap(); + data["partCount"] = OSD.FromInteger(prims.Count); + int partNum = 0; + foreach (SceneObjectPart part in prims) + { + string partTempID = "part" + partNum; + data[partTempID] = OSD.FromUUID(part.UUID); + partNum++; + } + //We also include the IDs of beforeDelinkGroups, for now it is more for sanity checking at the receiving end, so that the receiver + //could make sure its delink starts with the same linking state of the groups/prims. + data["beforeGroupsCount"] = OSD.FromInteger(beforeDelinkGroups.Count); + int groupNum = 0; + foreach (SceneObjectGroup affectedGroup in beforeDelinkGroups) + { + string groupTempID = "beforeGroup" + groupNum; + data[groupTempID] = OSD.FromUUID(affectedGroup.UUID); + groupNum++; + } + + //include the property values of each object after delinking, for synchronizing the values + data["afterGroupsCount"] = OSD.FromInteger(beforeDelinkGroups.Count); + groupNum = 0; + foreach (SceneObjectGroup afterGroup in afterDelinkGroups) + { + string groupTempID = "afterGroup" + groupNum; + string sogxml = SceneObjectSerializer.ToXml2Format(afterGroup); + data[groupTempID] = OSD.FromString(sogxml); + groupNum++; + } + + SymmetricSyncMessage rsm = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.DelinkObject, OSDParser.SerializeJsonString(data)); + SendDelinkObjectToRelevantSyncConnectors(beforeDelinkGroups, rsm); + } public void PublishSceneEvent(EventManager.EventNames ev, Object[] evArgs) { @@ -558,6 +596,25 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule } } + private void SendDelinkObjectToRelevantSyncConnectors(List beforeDelinkGroups, SymmetricSyncMessage syncMsg) + { + HashSet syncConnectorsSent = new HashSet(); + + foreach (SceneObjectGroup sog in beforeDelinkGroups) + { + List syncConnectors = GetSyncConnectorsForObjectUpdates(sog); + foreach (SyncConnector connector in syncConnectors) + { + if (!syncConnectorsSent.Contains(connector.ConnectorNum)) + { + m_log.Debug(LogHeader + " send DeLinkObject to " + connector.Description); + connector.EnqueueOutgoingUpdate(sog.UUID, syncMsg.ToBytes()); + syncConnectorsSent.Add(connector.ConnectorNum); + } + } + } + } + //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) private void SendSceneEventToRelevantSyncConnectors(string init_actorID, SymmetricSyncMessage rsm) diff --git a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/SymmetricSyncMessage.cs b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/SymmetricSyncMessage.cs index 381216f132..cd893b26af 100755 --- a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/SymmetricSyncMessage.cs +++ b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/SymmetricSyncMessage.cs @@ -31,6 +31,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule UpdatedObject, // objects RemovedObject, // objects LinkObject, + DelinkObject, RegionName, //RegionStatus, ActorID, diff --git a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/SyncConnector.cs b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/SyncConnector.cs index 105ce77559..1620262886 100755 --- a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/SyncConnector.cs +++ b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/SyncConnector.cs @@ -70,7 +70,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule { if (m_syncOtherSideRegionName == null) return String.Format("SyncConnector #{0}", m_connectorNum); - return String.Format("SyncConnector #{0} ({1:10})", m_connectorNum, m_syncOtherSideRegionName); + return String.Format("SyncConnector #{0} (Actor {2}, Region {1:10})", m_connectorNum, m_syncOtherSideRegionName, m_syncOtherSideActorID); } } diff --git a/OpenSim/Region/Framework/Interfaces/IRegionSyncModule.cs b/OpenSim/Region/Framework/Interfaces/IRegionSyncModule.cs index cb27f2f051..5bd5957706 100755 --- a/OpenSim/Region/Framework/Interfaces/IRegionSyncModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IRegionSyncModule.cs @@ -60,16 +60,16 @@ namespace OpenSim.Region.Framework.Interfaces void QueueSceneObjectPartForUpdate(SceneObjectPart part); void QueueScenePresenceForTerseUpdate(ScenePresence presence); - //SendSceneUpdates put 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 SendDeleteObject(SceneObjectGroup sog, bool softDelete); + void SendLinkObject(SceneObjectGroup linkedGroup, SceneObjectPart root, List children); + void SendDeLinkObject(List prims, List beforeDelinkGroups, List afterDelinkGroups); //In RegionSyncModule's implementation, //The following calls send out a message immediately, w/o putting it in the SyncConnector's outgoing queue. //May need some optimization there on the priorities. void SendTerrainUpdates(string lastUpdateActorID); - void SendDeleteObject(SceneObjectGroup sog, bool softDelete); - void SendLinkObject(SceneObjectGroup linkedGroup, SceneObjectPart root, List children); - //For propogating scene events to other actors void PublishSceneEvent(EventManager.EventNames ev, Object[] evArgs); diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index d37fcfbb14..16358c731c 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -1598,13 +1598,14 @@ namespace OpenSim.Region.Framework.Scenes //so should return quickly. if (m_parentScene.RegionSyncModule != null) { - //Tell other actors to link the SceneObjectParts together as a new group. But not updating the properties yet. - //The properties will be updated later when parentGroup.ScheduleGroupForFullUpdate() is called below. + //Tell other actors to link the SceneObjectParts together as a new group. parentGroup.SyncInfoUpdate(); m_parentScene.RegionSyncModule.SendLinkObject(parentGroup, root, children); } - //Schedule updates as in legacy OpenSim code, to send updates to viewers connected to this actor (at least needed for client managers) + //Schedule updates as in legacy OpenSim code, to send updates to viewers connected to this actor (at least needed for client managers). + //But timestamp won't be changed, so that when other actors get the update, they's simple ignore the updates since they already get them + //via the LinkObject message sent above. parentGroup.ScheduleGroupForFullUpdate_SyncInfoUnchanged(); //end of SYMMETRIC SYNC @@ -1628,6 +1629,11 @@ namespace OpenSim.Region.Framework.Scenes List childParts = new List(); List rootParts = new List(); List affectedGroups = new List(); + + //SYMMETRIC SYNC, record the new object groups after the delink operation + List beforeDelinkGroups = new List(); + List afterDelinkGroups = new List(); + // Look them all up in one go, since that is comparatively expensive // foreach (SceneObjectPart part in prims) @@ -1643,7 +1649,11 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectGroup group = part.ParentGroup; if (!affectedGroups.Contains(group)) + { affectedGroups.Add(group); + //SYMMETRIC SYNC + beforeDelinkGroups.Add(group); + } } } } @@ -1657,7 +1667,10 @@ namespace OpenSim.Region.Framework.Scenes // These are not in affected groups and will not be // handled further. Do the honors here. child.ParentGroup.HasGroupChanged = true; - child.ParentGroup.ScheduleGroupForFullUpdate(); + + //SYMMETRIC SYNC, delay ScheduleGroupForFullUpdate till the end of the delink operations. + //child.ParentGroup.ScheduleGroupForFullUpdate(); + afterDelinkGroups.Add(child.ParentGroup); } foreach (SceneObjectPart root in rootParts) @@ -1726,8 +1739,34 @@ namespace OpenSim.Region.Framework.Scenes { g.TriggerScriptChangedEvent(Changed.LINK); g.HasGroupChanged = true; // Persist - g.ScheduleGroupForFullUpdate(); + + //SYMMETRIC SYNC, delay ScheduleGroupForFullUpdate till the end of the delink operations. + //g.ScheduleGroupForFullUpdate(); + afterDelinkGroups.Add(g); } + + //SYMMETRIC SYNC + //set timestamp + long timeStamp = DateTime.Now.Ticks; + string actorID = m_parentScene.GetSyncActorID(); + foreach (SceneObjectGroup sog in afterDelinkGroups) + { + if (m_parentScene.RegionSyncModule != null) + { + sog.SyncInfoUpdate(timeStamp, actorID); ; + } + } + //Send out DelinkObject message to other actors to sychronize their object list + m_parentScene.RegionSyncModule.SendDeLinkObject(prims, beforeDelinkGroups, afterDelinkGroups); + + + //Schedule updates as in legacy OpenSim code, to send updates to viewers connected to this actor (at least needed for client managers). + //But timestamp won't be changed, so that when other actors get the update, they's simple ignore the updates since they already get them + foreach (SceneObjectGroup sog in afterDelinkGroups) + { + sog.ScheduleGroupForFullUpdate_SyncInfoUnchanged(); + } + //end of SYMMETRIC SYNC } finally { diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 94c619684a..0b03d2c242 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -3862,7 +3862,15 @@ namespace OpenSim.Region.Framework.Scenes public void SyncInfoUpdate() { long timeStamp = DateTime.Now.Ticks; - string actorID = m_scene.ActorSyncModule.ActorID; + string actorID = m_scene.GetSyncActorID(); + foreach (SceneObjectPart part in Parts) + { + part.SyncInfoUpdate(timeStamp, actorID); + } + } + + public void SyncInfoUpdate(long timeStamp, string actorID) + { foreach (SceneObjectPart part in Parts) { part.SyncInfoUpdate(timeStamp, actorID); diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index daf92035a8..8aa4ca4516 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -4940,7 +4940,7 @@ namespace OpenSim.Region.Framework.Scenes { if (m_parentGroup != null) { - m_lastUpdateActorID = m_parentGroup.Scene.ActorSyncModule.ActorID; + m_lastUpdateActorID = m_parentGroup.Scene.GetSyncActorID(); } else { @@ -4967,7 +4967,7 @@ namespace OpenSim.Region.Framework.Scenes // ScheduleFullUpdate() is called when m_parentGroup == null if (m_parentGroup != null && m_parentGroup.Scene != null && m_parentGroup.Scene.ActorSyncModule != null) { - SyncInfoUpdate(DateTime.Now.Ticks, m_parentGroup.Scene.ActorSyncModule.ActorID); + SyncInfoUpdate(DateTime.Now.Ticks, m_parentGroup.Scene.GetSyncActorID()); } }