diff --git a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs index 8813e437da..6e1ba52386 100644 --- a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs +++ b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs @@ -333,7 +333,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule //private void RegionSyncModule_OnObjectBeingRemovedFromScene(SceneObjectGroup sog) public void SendDeleteObject(SceneObjectGroup sog, bool softDelete) { - //m_log.DebugFormat("RegionSyncModule_OnObjectBeingRemovedFromScene called at time {0}:{1}:{2}", DateTime.Now.Minute, DateTime.Now.Second, DateTime.Now.Millisecond); + m_log.DebugFormat("SendDeleteObject called for object {0}", sog.UUID); //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)) @@ -351,14 +351,14 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule } - public void SendLinkObject(SceneObjectPart root, List children) + public void SendLinkObject(SceneObjectGroup linkedGroup, SceneObjectPart root, List children) { if(children.Count==0) return; OSDMap data = new OSDMap(); - //string sogxml = SceneObjectSerializer.ToXml2Format(linkedGroup); - //data["linkedGroup"]=OSD.FromString(sogxml); - data["root"] = OSD.FromUUID(root.UUID); + string sogxml = SceneObjectSerializer.ToXml2Format(linkedGroup); + data["linkedGroup"]=OSD.FromString(sogxml); + data["rootID"] = OSD.FromUUID(root.UUID); data["partCount"] = OSD.FromInteger(children.Count); data["actorID"] = OSD.FromString(m_actorID); int partNum = 0; @@ -369,7 +369,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule } SymmetricSyncMessage rsm = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.LinkObject, OSDParser.SerializeJsonString(data)); - SendObjectUpdateToRelevantSyncConnectors(root.ParentGroup, rsm); + SendObjectUpdateToRelevantSyncConnectors(linkedGroup, rsm); } @@ -1073,6 +1073,8 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule { Scene.ObjectUpdateResult updateResult = m_scene.AddOrUpdateObjectBySynchronization(sog); + m_log.Debug(LogHeader + " handle update message of object " + sog.UUID); + //if (added) switch (updateResult) { @@ -1157,14 +1159,17 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule bool softDelete = data["softDelete"].AsBoolean(); SceneObjectGroup sog = m_scene.SceneGraph.GetGroupByPrim(sogUUID); + if (sog != null) { if (!softDelete) { + m_log.Debug(LogHeader + " hard delete object " + sog.UUID); m_scene.DeleteSceneObjectBySynchronization(sog); } else { + m_log.Debug(LogHeader + " soft delete object " + sog.UUID); m_scene.UnlinkSceneObject(sog, true); } } @@ -1187,9 +1192,9 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule } string init_actorID = data["actorID"].AsString(); - //string sogxml = data["linkedGroup"].AsString(); - //SceneObjectGroup linkedGroup = SceneObjectSerializer.FromXml2Format(sogxml); - UUID rootID = data["root"].AsUUID(); + string sogxml = data["linkedGroup"].AsString(); + SceneObjectGroup linkedGroup = SceneObjectSerializer.FromXml2Format(sogxml); + UUID rootID = data["rootID"].AsUUID(); int partCount = data["partCount"].AsInteger(); List childrenIDs = new List(); @@ -1199,7 +1204,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule childrenIDs.Add(data[partTempID].AsUUID()); } - m_scene.LinkObjectBySync(rootID, childrenIDs); + m_scene.LinkObjectBySync(linkedGroup, rootID, childrenIDs); //if this is a relay node, forwards the event if (m_isSyncRelay) diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs index 276fcfe9a2..4771a8dd7b 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs @@ -610,14 +610,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain m_lastUpdateActorID = actorID; } - /* - public void CheckForTerrainUpdatesBySynchronization(long timeStamp, string actorID) - { - SyncInfoUpdate(timeStamp, actorID); - CheckForTerrainUpdates(false); - } - * */ - public void TaintTerrianBySynchronization(long timeStamp, string actorID) { SyncInfoUpdate(timeStamp, actorID); diff --git a/OpenSim/Region/Framework/Interfaces/IRegionSyncModule.cs b/OpenSim/Region/Framework/Interfaces/IRegionSyncModule.cs index 41629c20d6..cb27f2f051 100755 --- a/OpenSim/Region/Framework/Interfaces/IRegionSyncModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IRegionSyncModule.cs @@ -68,7 +68,7 @@ namespace OpenSim.Region.Framework.Interfaces //May need some optimization there on the priorities. void SendTerrainUpdates(string lastUpdateActorID); void SendDeleteObject(SceneObjectGroup sog, bool softDelete); - void SendLinkObject(SceneObjectPart root, List children); + 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/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index e810d502e1..88b848d6ad 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -755,7 +755,7 @@ namespace OpenSim.Region.Framework.Scenes /// /// /// - public void LinkObjectBySync(UUID rootID, List childrenIDs) + public void LinkObjectBySync(SceneObjectGroup linkedGroup, UUID rootID, List childrenIDs) { m_log.Debug("Start to LinkObjectBySync"); DebugSceneObjectGroups(); @@ -779,18 +779,30 @@ namespace OpenSim.Region.Framework.Scenes continue; } + m_log.Debug("to link part " + part.DebugObjectPartProperties()); + children.Add(part); } //Leverage the LinkObject implementation to get the book keeping of Group and Parts relations right m_sceneGraph.LinkObjectsBySync(root, children); + + + //The properties of the newly linked object should be updated later with another UpdatedObject message. //Set the property values as in the incoming copy of the object group - //SceneObjectGroup localGroup = root.ParentGroup; - //localGroup.UpdateObjectProperties(linkedGroup); + SceneObjectGroup localGroup = root.ParentGroup; + localGroup.UpdateObjectProperties(linkedGroup); + //debug + m_log.Debug("after SceneGraph.LinkObjectsBySync, the newly linked group is \n" + root.ParentGroup.DebugObjectUpdateResult()); + m_log.Debug("parts before linking now have properties: "); + foreach (SceneObjectPart part in children) + { + m_log.Debug(part.DebugObjectPartProperties()); + } } #endregion //SYMMETRIC SYNC diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 987468f1c5..ec7b18e679 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -1577,25 +1577,11 @@ namespace OpenSim.Region.Framework.Scenes } - //SYMMETRIC SYNC - //Send out a LinkObject message for synchronization purpose, before other object-update sync messages are sent out. - //We need to do this before the calling to parentGroup.LinkToGroup() below, as LinkToGroup will trigger - //SendDeleteObject message to be sent out. - - // ------------- NOTE: This needs further optimization, as we don't want to block on sending messages while inside the lock. ------------- - // However, we also want to make sure that the LinkObject message is sent out with high priority and sent - // earlier than the object update message triggered by the ScheduleGroupForFullUpdate() function below - 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. - m_parentScene.RegionSyncModule.SendLinkObject(root, children); - } - - //end of SYMMETRIC SYNC foreach (SceneObjectGroup child in childGroups) { + m_log.Debug("linking child " + child.UUID + " to parentGroup " + parentGroup.UUID); + parentGroup.LinkToGroup(child); // this is here so physics gets updated! @@ -1603,13 +1589,25 @@ namespace OpenSim.Region.Framework.Scenes child.AbsolutePosition = child.AbsolutePosition; } - - // We need to explicitly resend the newly link prim's object properties since no other actions - // occur on link to invoke this elsewhere (such as object selection) parentGroup.RootPart.CreateSelected = true; parentGroup.TriggerScriptChangedEvent(Changed.LINK); parentGroup.HasGroupChanged = true; - parentGroup.ScheduleGroupForFullUpdate(); + + //SYMMETRIC SYNC + //Schedule a LinkObject message for synchronization purpose. This will lead to enqueue a LinkObject message in SyncConnector's outgoingQueue, + //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. + 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) + parentGroup.ScheduleGroupForFullUpdate_SyncInfoUnchanged(); + + //end of SYMMETRIC SYNC } finally diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 625f6d6217..94c619684a 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -2128,8 +2128,8 @@ namespace OpenSim.Region.Framework.Scenes //SYMMETRIC SYNC //The DeleteObject message will be enqueued to be sent out by another thread, and the call will return quickly. - if (m_scene.RegionSyncModule != null) - m_scene.RegionSyncModule.SendDeleteObject(objectGroup, true); + //if (m_scene.RegionSyncModule != null) + // m_scene.RegionSyncModule.SendDeleteObject(objectGroup, true); //end of SYMMETRIC SYNC } @@ -3859,6 +3859,15 @@ namespace OpenSim.Region.Framework.Scenes } + public void SyncInfoUpdate() + { + long timeStamp = DateTime.Now.Ticks; + string actorID = m_scene.ActorSyncModule.ActorID; + foreach (SceneObjectPart part in Parts) + { + part.SyncInfoUpdate(timeStamp, actorID); + } + } #endregion } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 97745aac02..daf92035a8 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -4931,9 +4931,9 @@ namespace OpenSim.Region.Framework.Scenes set { m_lastUpdateActorID = value; } } - public void UpdateTimestamp() + public void UpdateTimestamp(long time) { - m_lastUpdateTimeStamp = DateTime.Now.Ticks; + m_lastUpdateTimeStamp = time; } public void SetLastUpdateActorID() @@ -4948,17 +4948,26 @@ namespace OpenSim.Region.Framework.Scenes } } + private Object m_SyncInfoLock = new Object(); + public void SyncInfoUpdate(long timeStamp, string actorID) + { + //update timestamp and actorID atomically + lock (m_SyncInfoLock) + { + UpdateTimestamp(timeStamp); + m_lastUpdateActorID = actorID; + } + } + + public void SyncInfoUpdate() { - //if (m_parentGroup == null || m_parentGroup.Scene==null || m_parentGroup.Scene.ActorSyncModule == null || m_parentGroup.Scene.ActorSyncModule.ActorID == null) - // return; //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, // ScheduleFullUpdate() is called when m_parentGroup == null - if (m_parentGroup != null && m_parentGroup.Scene != null && m_parentGroup.Scene.ActorSyncModule!=null) + if (m_parentGroup != null && m_parentGroup.Scene != null && m_parentGroup.Scene.ActorSyncModule != null) { - UpdateTimestamp(); - m_lastUpdateActorID = m_parentGroup.Scene.ActorSyncModule.ActorID; + SyncInfoUpdate(DateTime.Now.Ticks, m_parentGroup.Scene.ActorSyncModule.ActorID); } } @@ -5102,6 +5111,7 @@ namespace OpenSim.Region.Framework.Scenes public string DebugObjectPartProperties() { string debugMsg = "UUID " + UUID + ", Name " + Name + ", localID " + LocalId + ", lastUpdateActorID " + LastUpdateActorID + ", lastUpdateTimeStamp " + LastUpdateTimeStamp; + debugMsg += ", parentID " + ParentID + ", parentUUID " + ParentUUID; return debugMsg; } diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs index 536c0145c5..28fdffbb46 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs @@ -675,7 +675,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance return 0; } - m_log.DebugFormat("[Script] processing event {2} in state {3} to {0}.{1}, localID -{4}", m_PrimName, m_ScriptName, data.EventName, m_State, m_LocalID); + m_log.DebugFormat("[Script] processing event {2} in state {3} to {0}.{1}, localID-{4}", m_PrimName, m_ScriptName, data.EventName, m_State, m_LocalID); if (data.EventName == "timer")