diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs index c74e83c513..adc91ad1de 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs @@ -244,20 +244,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // Start the packet processing threads Watchdog.StartThread(IncomingPacketHandler, "Incoming Packets (" + m_scene.RegionInfo.RegionName + ")", ThreadPriority.Normal, false); Watchdog.StartThread(OutgoingPacketHandler, "Outgoing Packets (" + m_scene.RegionInfo.RegionName + ")", ThreadPriority.Normal, false); - m_elapsedMSSinceLastStatReport = Environment.TickCount; - System.Timers.Timer packet_type_timer = new System.Timers.Timer(60000); - packet_type_timer.Elapsed +=new System.Timers.ElapsedEventHandler(packet_type_timer_Elapsed); - packet_type_timer.AutoReset = true; - packet_type_timer.Start(); - } - - void packet_type_timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) - { - for (int i = 0; i < 9; ++i) - { - int val = Interlocked.Exchange(ref CatCounts[i], 0); - m_log.WarnFormat("OutgoingPacket type {0} count = {1}", i, val); - } + m_elapsedMSSinceLastStatReport = Environment.TickCount; } public new void Stop() diff --git a/OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs b/OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs index 188b8b8a95..cbe3b8a2c0 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs @@ -27,7 +27,7 @@ using System; using OpenSim.Framework; -using OpenMetaverse; +using OpenMetaverse; using System.Threading; namespace OpenSim.Region.ClientStack.LindenUDP diff --git a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs index 18e547d6e4..a1e28aafda 100644 --- a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs +++ b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs @@ -13,6 +13,7 @@ using OpenSim.Region.CoreModules.Framework.InterfaceCommander; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes.Serialization; +using OpenSim.Region.Physics.Manager; using OpenSim.Services.Interfaces; using log4net; using System.Net; @@ -209,11 +210,11 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule foreach (string bucketName in m_propertyBucketNames) { //if (m_isSyncRelay || part.HasPropertyUpdatedLocallyInGivenBucket(bucketName)) - if(ToSendoutUpdate(part, bucketName)) + if(!part.ParentGroup.IsDeleted && HaveUpdatesToSendoutForSync(part, bucketName)) { lock (m_primUpdateLocks[bucketName]) { - m_log.Debug("Queueing to bucket " + bucketName + " with part " + part.Name + ", " + part.UUID); + //m_log.Debug("Queueing to bucket " + bucketName + " with part " + part.Name + ", " + part.UUID+" at pos "+part.GroupPosition.ToString()); m_primUpdates[bucketName][part.UUID] = part; } } @@ -236,7 +237,11 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule { if (!IsSyncingWithOtherActors()) { - //no SyncConnector connected. Do nothing. + //no SyncConnector connected. clear update queues and return. + foreach (string bucketName in m_propertyBucketNames) + { + m_primUpdates[bucketName].Clear(); + } return; } @@ -256,14 +261,26 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule { if (m_primUpdates[bucketName].Count > 0) { - //m_log.Debug(m_primUpdates[bucketName].Count + " updated parts in bucket " + bucketName); + //m_log.DebugFormat(m_primUpdates[bucketName].Count + " to send {0} updated parts in bucket {1}", m_primUpdates[bucketName].Count, bucketName); + lock (m_primUpdateLocks[bucketName]) { updated = true; - primUpdates.Add(bucketName, new List(m_primUpdates[bucketName].Values)); - + //primUpdates.Add(bucketName, new List(m_primUpdates[bucketName].Values)); + + //copy the update list + List updateList = new List(); + foreach (SceneObjectPart part in m_primUpdates[bucketName].Values) + { + if (!part.ParentGroup.IsDeleted) + { + //m_log.DebugFormat("include {0},{1} in update list", part.Name, part.UUID); + updateList.Add(part); + } + } + primUpdates.Add(bucketName, updateList); + m_primUpdates[bucketName].Clear(); - } } } @@ -296,23 +313,9 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule { if (primUpdates.ContainsKey(bucketName) && primUpdates[bucketName].Count > 0) { - /* - foreach (SceneObjectGroup sog in primUpdates[bucketName]) - { - - //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 - sog.UpdateTaintedBucketSyncInfo(timeStamp); - if (m_isSyncRelay || (!sog.IsDeleted && CheckObjectForSendingUpdate(sog))) - { - //send - string sogxml = SceneObjectSerializer.ToXml2Format(sog); - SymmetricSyncMessage syncMsg = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.UpdatedObject, sogxml); - SendObjectUpdateToRelevantSyncConnectors(sog, syncMsg); - } - } - * */ //m_log.Debug(LogHeader + " calling update sender for bucket " + bucketName); m_primUpdatesPerBucketSender[bucketName](bucketName, primUpdates[bucketName]); + primUpdates[bucketName].Clear(); } } foreach (ScenePresence presence in presenceUpdates) @@ -397,11 +400,31 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule //no SyncConnector connected. Do nothing. return; } - m_log.DebugFormat(LogHeader + "SendNewObject called for object {0}, {1}", sog.Name, sog.UUID); + + /* + //m_log.DebugFormat(LogHeader + " SendNewObject called for object {0}, {1}", sog.Name, sog.UUID); + //This is a new object (newly rezzed). Send out updates for all properties. + //For now, a complete list of object properties include properties + //in its xml serialization, plus the set of Physics properties as in Physics bucket + OSDMap data = new OSDMap(); string sogxml = SceneObjectSerializer.ToXml2Format(sog); - SymmetricSyncMessage rsm = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.NewObject, sogxml); - SendObjectUpdateToRelevantSyncConnectors(sog, rsm); + data["sogxml"] = OSD.FromString(sogxml); + OSDArray partArray = new OSDArray(); + foreach (SceneObjectPart part in sog.Parts){ + OSDMap partData = PhysicsBucketPropertiesEncoder(m_physicsBucketName, part); + partArray.Add(partData); + } + data["partPhysicsProperties"] = partArray; + //string sogxml = SceneObjectSerializer.ToXml2Format(sog); + SymmetricSyncMessage rsm = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.NewObject, OSDParser.SerializeJsonString(data)); + + * */ + + SymmetricSyncMessage rsm = CreateNewObjectMessage(sog); + + //SendObjectUpdateToRelevantSyncConnectors(sog, rsm); + SendSceneEventToRelevantSyncConnectors(m_actorID, rsm, sog); } /// @@ -419,7 +442,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule return; } - m_log.DebugFormat(LogHeader+"SendDeleteObject called for object {0}", sog.UUID); + //m_log.DebugFormat(LogHeader+"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)) @@ -433,7 +456,8 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule data["softDelete"] = OSD.FromBoolean(softDelete); SymmetricSyncMessage rsm = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.RemovedObject, OSDParser.SerializeJsonString(data)); - SendObjectUpdateToRelevantSyncConnectors(sog, rsm); + //SendObjectUpdateToRelevantSyncConnectors(sog, rsm); + SendSceneEventToRelevantSyncConnectors(m_actorID, rsm, sog); } @@ -461,13 +485,16 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule string partTempID = "part"+partNum; data[partTempID] = OSD.FromUUID(part.UUID); partNum++; + + m_log.Debug("SendLinkObject to link " + part.ParentGroup.Name + "," + part.UUID + " with " + root.Name+","+root.UUID); } - m_log.Debug(LogHeader + " to SendLinkObject to link " + children.Count + " parts to " + root.Name); - m_log.Debug("LinkedObject: "+sogxml); + m_log.Debug(LogHeader + " to SendLinkObject to link " + children.Count + " parts to " + root.Name + "," + root.UUID); + //m_log.Debug("LinkedObject: "+sogxml); SymmetricSyncMessage rsm = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.LinkObject, OSDParser.SerializeJsonString(data)); - SendObjectUpdateToRelevantSyncConnectors(linkedGroup, rsm); + //SendObjectUpdateToRelevantSyncConnectors(linkedGroup, rsm); + SendSceneEventToRelevantSyncConnectors(m_actorID, rsm, linkedGroup); } public void SendDeLinkObject(List prims, List beforeDelinkGroups, List afterDelinkGroups) @@ -592,6 +619,9 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule case EventManager.EventNames.Attach: OnLocalAttach((uint)evArgs[0], (UUID)evArgs[1], (UUID)evArgs[2]); return; + case EventManager.EventNames.PhysicsCollision: + OnLocalPhysicsCollision((UUID)evArgs[0], (OSDArray)evArgs[1]); + return; default: return; } @@ -718,8 +748,20 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule private delegate void PrimUpdatePerBucketSender(string bucketName, List primUpdates); private Dictionary m_primUpdatesPerBucketSender = new Dictionary(); - //Timestamps that record the last time each any updates have been sent out for a given bucket - private Dictionary m_lastUpdateSentTime = new Dictionary(); + + /* + //The functions that encode properties in each bucket. For now, + //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. + //TO DO: redesign the interface once the bucket encoders working on more + //consistent/specific arguments. + private delegate string UpdatePerBucketEncoder(string bucketName, Object arg); + private Dictionary m_updatePerBucketEncoder = new Dictionary(); + + //Decoders of properties in each bucket + private delegate void UpdatePerBucketDecoder(string bucketName, string encoding, out Object outData); + private Dictionary m_updatePerBucketDecoder = new Dictionary(); + * */ private object m_updateScenePresenceLock = new object(); private Dictionary m_presenceUpdates = new Dictionary(); @@ -733,6 +775,48 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule m_log.Warn("[REGION SYNC MODULE]: StatsTimerElapsed -- NOT yet implemented."); } + private SymmetricSyncMessage CreateNewObjectMessage(SceneObjectGroup sog) + { + OSDMap data = new OSDMap(); + string sogxml = SceneObjectSerializer.ToXml2Format(sog); + data["sogxml"] = OSD.FromString(sogxml); + OSDArray partArray = new OSDArray(); + foreach (SceneObjectPart part in sog.Parts) + { + OSDMap partData = PhysicsBucketPropertiesEncoder(m_physicsBucketName, part); + partArray.Add(partData); + } + data["partPhysicsProperties"] = partArray; + //string sogxml = SceneObjectSerializer.ToXml2Format(sog); + SymmetricSyncMessage rsm = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.NewObject, OSDParser.SerializeJsonString(data)); + + return rsm; + } + + private void HandleGetTerrainRequest(SyncConnector connector) + { + string msgData = m_scene.Heightmap.SaveToXmlString(); + long lastUpdateTimeStamp; + string lastUpdateActorID; + m_scene.RequestModuleInterface().GetSyncInfo(out lastUpdateTimeStamp, out lastUpdateActorID); + + OSDMap data = new OSDMap(3); + data["terrain"] = OSD.FromString(msgData); + data["actorID"] = OSD.FromString(lastUpdateActorID); + data["timeStamp"] = OSD.FromLong(lastUpdateTimeStamp); + + SymmetricSyncMessage syncMsg = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.Terrain, OSDParser.SerializeJsonString(data)); + connector.Send(syncMsg); + } + + private void HandleGetObjectRequest(SyncConnector connector, SceneObjectGroup sog) + { + SymmetricSyncMessage syncMsg = CreateNewObjectMessage(sog); + + //SendToSyncConnector(connector, sog, syncMsg); + connector.EnqueueOutgoingUpdate(sog.UUID, syncMsg.ToBytes()); + } + //Read in configuration for which property-bucket each property belongs to, and the description of each bucket private void PopulatePropertyBucketMap(IConfig config) { @@ -747,95 +831,158 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule //Going forward, we may serialize the properties differently, e.g. using OSDMap private void PrimUpdatesGeneralBucketSender(string bucketName, List primUpdates) { - UpdateBucektLastSentTime(bucketName); - Dictionary updatedObjects = new Dictionary(); foreach (SceneObjectPart part in primUpdates) { - updatedObjects[part.ParentGroup.UUID] = part.ParentGroup; + if(!part.ParentGroup.IsDeleted) + updatedObjects[part.ParentGroup.UUID] = part.ParentGroup; } + long timeStamp = DateTime.Now.Ticks; foreach (SceneObjectGroup sog in updatedObjects.Values) { - sog.UpdateTaintedBucketSyncInfo(bucketName, DateTime.Now.Ticks); //this update the timestamp and clear the taint info of the bucket - string sogxml = SceneObjectSerializer.ToXml2Format(sog); - SymmetricSyncMessage syncMsg = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.UpdatedObject, sogxml); + sog.UpdateTaintedBucketSyncInfo(bucketName, timeStamp); //this update the timestamp and clear the taint info of the bucket + string sogGeneralBucketEncoding = SceneObjectSerializer.ToXml2Format(sog); + //string sogGeneralBucketEncoding = GeneralBucketPropertiesEncoder(bucketName, sog, null); + SymmetricSyncMessage syncMsg = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.UpdatedObject, sogGeneralBucketEncoding); + + //TEMP DEBUG + foreach (SceneObjectPart part in sog.Parts) + { + if (part.IsAttachment) + { + m_log.Debug(LogHeader + "PrimUpdatesGeneralBucketSender: part " + part.Name + "," + part.UUID + ", IsAttachment = true"); + } + } + lock (m_stats) m_statSOGBucketOut++; + + //m_log.DebugFormat(LogHeader + " calling SendObjectUpdateToRelevantSyncConnectors for general bucket for sog {0},{1}", sog.Name, sog.UUID); + SendObjectUpdateToRelevantSyncConnectors(sog, syncMsg); + + //clear the taints + foreach (SceneObjectPart part in sog.Parts) + { + part.BucketSyncInfoList[bucketName].ClearBucketTaintBySync(); + } } + //UpdateBucektLastSentTime(bucketName, timeStamp); + } + + private string GeneralBucketPropertiesEncoder(string bucketName, Object sog) + { + if (sog is SceneObjectGroup) + { + SceneObjectGroup group = (SceneObjectGroup)sog; + return SceneObjectSerializer.ToXml2Format(group); + } + else + return String.Empty; + } + + private void GeneralBucketPropertiesDecoder(string bucketName, string encoding, out Object sog) + { + SceneObjectGroup group = SceneObjectSerializer.FromXml2Format(encoding); + sog = (Object)group; + } private void PrimUpdatesPhysicsBucketSender(string bucketName, List primUpdates) { - UpdateBucektLastSentTime(bucketName); - foreach (SceneObjectPart updatedPart in primUpdates) { + if (updatedPart.ParentGroup.IsDeleted) + continue; + updatedPart.UpdateTaintedBucketSyncInfo(bucketName, DateTime.Now.Ticks); - OSDMap data = new OSDMap(); - - data["UUID"] = OSD.FromUUID(updatedPart.UUID); - //data["UUID"] = OSD.FromUUID(pa.UUID); - data["Bucket"] = OSD.FromString(bucketName); - - data["GroupPosition"] = OSD.FromVector3(updatedPart.GroupPosition); - data["OffsetPosition"] = OSD.FromVector3(updatedPart.OffsetPosition); - data["Scale"] = OSD.FromVector3(updatedPart.Scale); - data["AngularVelocity"] = OSD.FromVector3(updatedPart.AngularVelocity); - data["RotationOffset"] = OSD.FromQuaternion(updatedPart.RotationOffset); - - Physics.Manager.PhysicsActor pa = updatedPart.PhysActor; - if (pa != null) - { - - data["Size"] = OSD.FromVector3(pa.Size); - data["Position"] = OSD.FromVector3(pa.Position); - data["Force"] = OSD.FromVector3(pa.Force); - data["Velocity"] = OSD.FromVector3(pa.Velocity); - data["RotationalVelocity"] = OSD.FromVector3(pa.RotationalVelocity); - data["PA_Acceleration"] = OSD.FromVector3(pa.Acceleration); - data["Torque"] = OSD.FromVector3(pa.Torque); - data["Orientation"] = OSD.FromQuaternion(pa.Orientation); - data["IsPhysical"] = OSD.FromBoolean(pa.IsPhysical); - data["Flying"] = OSD.FromBoolean(pa.Flying); - data["Kinematic"] = OSD.FromBoolean(pa.Kinematic); - data["Buoyancy"] = OSD.FromReal(pa.Buoyancy); - data["CollidingGround"] = OSD.FromBoolean(pa.CollidingGround); - data["IsColliding"] = OSD.FromBoolean(pa.IsColliding); - } - - data["LastUpdateTimeStamp"] = OSD.FromLong(updatedPart.BucketSyncInfoList[bucketName].LastUpdateTimeStamp); - data["LastUpdateActorID"] = OSD.FromString(updatedPart.BucketSyncInfoList[bucketName].LastUpdateActorID); - - //m_log.Debug(LogHeader + " Send out Physics Bucket updates for " + updatedPart.Name + ". GroupPosition: " + updatedPart.GroupPosition.ToString()); - - SymmetricSyncMessage syncMsg = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.UpdatedBucketProperties, OSDParser.SerializeJsonString(data)); + //string partPhysicsBucketEncoding = PhysicsBucketPropertiesEncoder(bucketName, updatedPart); + OSDMap partData = PhysicsBucketPropertiesEncoder(bucketName, updatedPart); + 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()); + + //TEMP DEBUG + if (updatedPart.IsAttachment) + { + m_log.Debug(LogHeader + "PrimUpdatesPhysicsBucketSender: part " + updatedPart.Name + "," + updatedPart.UUID + ", IsAttachment = true"); + } + + lock (m_stats) m_statPhysBucketOut++; SendObjectUpdateToRelevantSyncConnectors(updatedPart, syncMsg); + + //clear the taints + updatedPart.BucketSyncInfoList[bucketName].ClearBucketTaintBySync(); } + //UpdateBucektLastSentTime(bucketName); } - private void UpdateBucektLastSentTime(string bucketName) + private OSDMap PhysicsBucketPropertiesEncoder(string bucketName, SceneObjectPart updatedPart) { - long timeStamp = DateTime.Now.Ticks; - /* - if (m_lastUpdateSentTime.ContainsKey(bucketName)) + OSDMap data = new OSDMap(); + + data["UUID"] = OSD.FromUUID(updatedPart.UUID); + //data["UUID"] = OSD.FromUUID(pa.UUID); + data["Bucket"] = OSD.FromString(bucketName); + + data["GroupPosition"] = OSD.FromVector3(updatedPart.GroupPosition); + data["OffsetPosition"] = OSD.FromVector3(updatedPart.OffsetPosition); + data["Scale"] = OSD.FromVector3(updatedPart.Scale); + data["AngularVelocity"] = OSD.FromVector3(updatedPart.AngularVelocity); + data["RotationOffset"] = OSD.FromQuaternion(updatedPart.RotationOffset); + + Physics.Manager.PhysicsActor pa = updatedPart.PhysActor; + if (pa != null) { - m_lastUpdateSentTime[bucketName] = timeStamp; + + data["Size"] = OSD.FromVector3(pa.Size); + data["Position"] = OSD.FromVector3(pa.Position); + data["Force"] = OSD.FromVector3(pa.Force); + data["Velocity"] = OSD.FromVector3(pa.Velocity); + data["RotationalVelocity"] = OSD.FromVector3(pa.RotationalVelocity); + data["PA_Acceleration"] = OSD.FromVector3(pa.Acceleration); + data["Torque"] = OSD.FromVector3(pa.Torque); + data["Orientation"] = OSD.FromQuaternion(pa.Orientation); + data["IsPhysical"] = OSD.FromBoolean(pa.IsPhysical); + data["Flying"] = OSD.FromBoolean(pa.Flying); + data["Kinematic"] = OSD.FromBoolean(pa.Kinematic); + data["Buoyancy"] = OSD.FromReal(pa.Buoyancy); + data["CollidingGround"] = OSD.FromBoolean(pa.CollidingGround); + data["IsColliding"] = OSD.FromBoolean(pa.IsColliding); + + //m_log.DebugFormat("{0}: PhysBucketSender for {1}, pos={2}", LogHeader, updatedPart.UUID.ToString(), pa.Position.ToString()); + } + + data["LastUpdateTimeStamp"] = OSD.FromLong(updatedPart.BucketSyncInfoList[bucketName].LastUpdateTimeStamp); + 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; + } + + private void PhysicsBucketPropertiesDecoder(string bucketName, SymmetricSyncMessage msg, out Object sog) + { + OSDMap data = DeserializeMessage(msg); + sog = (Object)data; + } + + private bool HaveUpdatesToSendoutForSync(SceneObjectPart part, string bucketName) + { + if (m_isSyncRelay) + { + return (part.HasPropertyUpdatedLocally(bucketName) || part.HasPropertyUpdatedBySync(bucketName)); } else { - m_lastUpdateSentTime.Add(bucketName, timeStamp); + return part.HasPropertyUpdatedLocally(bucketName); } - * */ - m_lastUpdateSentTime[bucketName] = timeStamp; - } - private bool ToSendoutUpdate(SceneObjectPart part, string bucketName) - { + //return (m_isSyncRelay || part.HasPropertyUpdatedLocallyInGivenBucket(bucketName)); + + /* if (!m_isSyncRelay) { return part.HasPropertyUpdatedLocallyInGivenBucket(bucketName); @@ -846,24 +993,34 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule return true; else return false; + * */ } + //by default, there are two property buckets: the "General" bucket and the "Physics" bucket. + private string m_generalBucketName = "General"; + private string m_physicsBucketName = "Physics"; //If nothing configured in the config file, this is the default settings for grouping properties into different bucket private void PopulatePropertyBuketMapByDefault() { - //by default, there are two property buckets: the "General" bucket and the "Physics" bucket. - string generalBucketName = "General"; - string physicsBucketName = "Physics"; - m_propertyBucketNames.Add(generalBucketName); - m_propertyBucketNames.Add(physicsBucketName); + + m_propertyBucketNames.Add(m_generalBucketName); + m_propertyBucketNames.Add(m_physicsBucketName); m_maxNumOfPropertyBuckets = m_propertyBucketNames.Count; //Linking each bucket with the sender function that serializes the properties in the bucket and send out sync message - m_primUpdatesPerBucketSender.Add("General", PrimUpdatesGeneralBucketSender); - m_primUpdatesPerBucketSender.Add("Physics", PrimUpdatesPhysicsBucketSender); + m_primUpdatesPerBucketSender.Add(m_generalBucketName, PrimUpdatesGeneralBucketSender); + m_primUpdatesPerBucketSender.Add(m_physicsBucketName, PrimUpdatesPhysicsBucketSender); - m_lastUpdateSentTime.Add("General", 0); - m_lastUpdateSentTime.Add("Physics", 0); + /* + m_updatePerBucketEncoder.Add(generalBucketName, GeneralBucketPropertiesEncoder); + m_updatePerBucketEncoder.Add(physicsBucketName, PhysicsBucketPropertiesEncoder); + + m_updatePerBucketDecoder.Add(generalBucketName, GeneralBucketPropertiesDecoder); + m_updatePerBucketDecoder.Add(physicsBucketName, PhysicsBucketPropertiesDecoder); + * */ + + //m_lastUpdateSentTime.Add("General", 0); + //m_lastUpdateSentTime.Add("Physics", 0); //Mapping properties to buckets. foreach (SceneObjectPartProperties property in Enum.GetValues(typeof(SceneObjectPartProperties))) @@ -889,11 +1046,11 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule case SceneObjectPartProperties.Buoyancy: case SceneObjectPartProperties.IsCollidingGround: case SceneObjectPartProperties.IsColliding: - m_primPropertyBucketMap.Add(property, physicsBucketName); + m_primPropertyBucketMap.Add(property, m_physicsBucketName); break; default: //all other properties belong to the "General" bucket. - m_primPropertyBucketMap.Add(property, generalBucketName); + m_primPropertyBucketMap.Add(property, m_generalBucketName); break; } } @@ -921,6 +1078,8 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule //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); + connector.EnqueueOutgoingUpdate(sog.UUID, syncMsg.ToBytes()); } } @@ -934,6 +1093,10 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule { //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); + connector.EnqueueOutgoingUpdate(updatedPart.UUID, syncMsg.ToBytes()); } } @@ -959,9 +1122,10 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule //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) + private void SendSceneEventToRelevantSyncConnectors(string init_actorID, SymmetricSyncMessage rsm, SceneObjectGroup sog) { - List syncConnectors = GetSyncConnectorsForSceneEvents(init_actorID, rsm); + //TODO: need to pick connectors based on sog position (quark it resides in) + List syncConnectors = GetSyncConnectorsForSceneEvents(init_actorID, rsm, sog); foreach (SyncConnector connector in syncConnectors) { @@ -1015,6 +1179,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule //in other parts as well, so we are sending to all connectors. ForEachSyncConnector(delegate(SyncConnector connector) { + //if(!connector.OtherSideActorID.Equals(sog.BucketSyncInfoUpdate[ syncConnectors.Add(connector); }); } @@ -1041,7 +1206,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule /// /// /// - private List GetSyncConnectorsForSceneEvents(string init_actorID, SymmetricSyncMessage rsm) + private List GetSyncConnectorsForSceneEvents(string init_actorID, SymmetricSyncMessage rsm, SceneObjectGroup sog) { List syncConnectors = new List(); if (m_isSyncRelay) @@ -1287,6 +1452,20 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule } m_log.WarnFormat("SyncStateReport -- Object count: {0}, Prim Count {1} ", sogList.Count, primCount); + foreach (SceneObjectGroup sog in sogList) + { + m_log.WarnFormat("SyncStateReport -- SOG: name {0}, UUID {1}, position {2}", sog.Name, sog.UUID, sog.AbsolutePosition); + } + + if (m_isSyncRelay) + { + SymmetricSyncMessage msg = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.SyncStateReport); + ForEachSyncConnector(delegate(SyncConnector connector) + { + connector.Send(msg); + }); + + } } private void SyncDebug(Object[] args) @@ -1415,7 +1594,8 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule private void DoInitialSync() { - m_scene.DeleteAllSceneObjects(); + //m_scene.DeleteAllSceneObjects(); + m_scene.DeleteAllSceneObjectsBySync(); SendSyncMessage(SymmetricSyncMessage.MsgType.RegionName, m_scene.RegionInfo.RegionName); m_log.WarnFormat("Sending region name: \"{0}\"", m_scene.RegionInfo.RegionName); @@ -1494,7 +1674,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule /// /// /// ActorID of the sender - public void HandleIncomingMessage(SymmetricSyncMessage msg, string senderActorID) + public void HandleIncomingMessage(SymmetricSyncMessage msg, string senderActorID, SyncConnector syncConnector) { lock (m_stats) m_statMsgsIn++; //Added senderActorID, so that we don't have to include actorID in sync messages -- TODO @@ -1503,7 +1683,8 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule case SymmetricSyncMessage.MsgType.GetTerrain: { //SendSyncMessage(SymmetricSyncMessage.MsgType.Terrain, m_scene.Heightmap.SaveToXmlString()); - SendTerrainUpdateMessage(); + //SendTerrainUpdateMessage(); + HandleGetTerrainRequest(syncConnector); return; } case SymmetricSyncMessage.MsgType.Terrain: @@ -1524,10 +1705,10 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule { if (e is SceneObjectGroup) { - string sogxml = SceneObjectSerializer.ToXml2Format((SceneObjectGroup)e); - SendSyncMessage(SymmetricSyncMessage.MsgType.NewObject, sogxml); - - //m_log.Debug(LogHeader + ": " + sogxml); + //string sogxml = SceneObjectSerializer.ToXml2Format((SceneObjectGroup)e); + //SendSyncMessage(SymmetricSyncMessage.MsgType.NewObject, sogxml); + SceneObjectGroup sog = (SceneObjectGroup)e; + HandleGetObjectRequest(syncConnector, sog); } } return; @@ -1537,8 +1718,8 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule break; case SymmetricSyncMessage.MsgType.UpdatedObject: { - HandleAddOrUpdateObjectBySynchronization(msg, senderActorID); - //HandleAddNewObject(sog); + //HandleAddOrUpdateObjectBySynchronization(msg, senderActorID); + HandleUpdateObjectBySynchronization(msg, senderActorID); return; } case SymmetricSyncMessage.MsgType.UpdatedBucketProperties: @@ -1572,10 +1753,16 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule case SymmetricSyncMessage.MsgType.ObjectGrabbing: case SymmetricSyncMessage.MsgType.ObjectDeGrab: case SymmetricSyncMessage.MsgType.Attach: + case SymmetricSyncMessage.MsgType.PhysicsCollision: { HandleRemoteEvent(msg, senderActorID); return; } + case SymmetricSyncMessage.MsgType.SyncStateReport: + { + SyncStateReport(null); + return; + } default: return; } @@ -1603,13 +1790,90 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule } private void HandleAddNewObject(SymmetricSyncMessage msg, string senderActorID) + { + + //string sogxml = Encoding.ASCII.GetString(msg.Data, 0, msg.Length); + //SceneObjectGroup sog = SceneObjectSerializer.FromXml2Format(sogxml); + OSDMap data = DeserializeMessage(msg); + + //First, create the object group and add it to Scene + string sogxml = data["sogxml"]; + SceneObjectGroup sog = SceneObjectSerializer.FromXml2Format(sogxml); + //Scene.ObjectUpdateResult updateResult = m_scene.AddOrUpdateObjectBySynchronization(sog); + + //m_log.DebugFormat("{0}: received NewObject sync message from {1}, for object {1}, {2}", LogHeader, senderActorID, sog.Name, sog.UUID); + + Scene.ObjectUpdateResult updateResult = m_scene.AddNewSceneObjectBySync(sog); + + //if this is a relay node, forward the event + if (m_isSyncRelay) + { + SendSceneEventToRelevantSyncConnectors(senderActorID, msg, sog); + } + + //Second, update the physics properties of each prim in the object + OSDArray partArray = (OSDArray)data["partPhysicsProperties"]; + for (int i = 0; i < partArray.Count; i++) + { + OSDMap partData = (OSDMap)partArray[i]; + UUID partUUID = partData["UUID"].AsUUID(); + + string bucketName = partData["Bucket"].AsString(); + + //m_log.DebugFormat("{0}: HandleUpdatedBucketProperties from {1}: for {2}/{3}", LogHeader, senderActorID, partUUID.ToString(), bucketName); + + BucketSyncInfo rBucketSyncInfo = new BucketSyncInfo(bucketName); + rBucketSyncInfo.LastUpdateTimeStamp = partData["LastUpdateTimeStamp"].AsLong(); + rBucketSyncInfo.LastUpdateActorID = partData["LastUpdateActorID"].AsString(); + // updatedPart.BucketSyncInfoList.Add(bucketName, rBucketSyncInfo); + + m_scene.UpdateObjectPartBucketProperties(bucketName, partUUID, data, rBucketSyncInfo); + } + //m_log.DebugFormat("{0}: after processing NewObject sync message from {1}, for object {1}, {2}", LogHeader, senderActorID, sog.Name, sog.UUID); + } + + private void HandleUpdateObjectBySynchronization(SymmetricSyncMessage msg, string senderActorID) { string sogxml = Encoding.ASCII.GetString(msg.Data, 0, msg.Length); SceneObjectGroup sog = SceneObjectSerializer.FromXml2Format(sogxml); + lock (m_stats) m_statSOGBucketIn++; - m_log.DebugFormat("{0}: received NewObject sync message from {1}, for object {1}, {2}", LogHeader, senderActorID, sog.Name, sog.UUID); + if (sog.IsDeleted) + { + SymmetricSyncMessage.HandleTrivial(LogHeader, msg, String.Format("Ignoring update on deleted object, UUID: {0}.", sog.UUID)); + return; + } + else + { + foreach (SceneObjectPart part in sog.Parts) + { + if (part.IsAttachment) + { + m_log.Debug(LogHeader + "HandleUpdateObjectBySynchronization: part " + part.Name + "," + part.UUID + ", IsAttachment = true"); + } + } + + //m_log.Debug(LogHeader + "HandleUpdateObjectBySynchronization: sog " + sog.Name + "," + sog.UUID); + + 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; + } + } - Scene.ObjectUpdateResult updateResult = m_scene.AddOrUpdateObjectBySynchronization(sog); } private void HandleAddOrUpdateObjectBySynchronization(SymmetricSyncMessage msg, string senderActorID) @@ -1625,7 +1889,8 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule { partnames += "(" + part.Name + ", " + part.UUID + ")"; } - m_log.Debug(LogHeader+" received "+msg.Type.ToString()+" from "+senderActorID+" about obj "+sog.Name+", "+sog.UUID+"; parts -- "+partnames); + + m_log.Debug(LogHeader+" received "+msg.Type.ToString()+" from "+senderActorID+" about obj "+sog.Name+", "+sog.UUID);//+"; parts -- "+partnames); * */ if (sog.IsDeleted) @@ -1635,6 +1900,14 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule } else { + foreach (SceneObjectPart part in sog.Parts) + { + if (part.IsAttachment) + { + m_log.Debug(LogHeader + "HandleAddOrUpdateObjectBySynchronization: part " + part.Name + "," + part.UUID + ", IsAttachment = true"); + } + } + Scene.ObjectUpdateResult updateResult = m_scene.AddOrUpdateObjectBySynchronization(sog); //if (added) @@ -1672,41 +1945,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule UUID partUUID = data["UUID"].AsUUID(); string bucketName = data["Bucket"].AsString(); - //m_log.DebugFormat("{0}: HandleUpdatedBucketProperties {1}: for {2}/{3}", LogHeader, senderActorID, partUUID.ToString(), bucketName); - - /* Commented out since OSDMap is now passed all the way through to the unpacker. - * Previous implementation is to create a SOP and copy the values into same and copy them out later. - SceneObjectPart updatedPart = new SceneObjectPart(); - updatedPart.GroupPosition = data["GroupPosition"].AsVector3(); - updatedPart.OffsetPosition = data["OffsetPosition"].AsVector3(); - updatedPart.RotationOffset = data["RotationOffset"].AsQuaternion(); - updatedPart.Velocity = data["Velocity"].AsVector3(); - updatedPart.AngularVelocity = data["AngularVelocity"].AsVector3(); - //Scale is a bit complex, we need to have Shape first -- not a good solution, but leave it as is so that we can move on, - updatedPart.Shape = new PrimitiveBaseShape(); - updatedPart.Scale = data["Scale"].AsVector3(); - - Dictionary updatedProperties = new Dictionary(); - updatedProperties.Add("GroupPosition", (Object)data["GroupPosition"].AsVector3()); - updatedProperties.Add("OffsetPosition", (Object)data["OffsetPosition"].AsVector3()); - updatedProperties.Add("RotationOffset", (Object)data["RotationOffset"].AsQuaternion()); - updatedProperties.Add("Velocity", (Object)data["Velocity"].AsVector3()); - updatedProperties.Add("AngularVelocity", (Object)data["AngularVelocity"].AsVector3()); - updatedProperties.Add("Scale", (Object)data["Scale"].AsVector3()); - */ - //Other properties to be included - /* - "Position": - "Size": - "Force": - "RotationalVelocity": - "PA_Acceleration": - "Torque": - "Orientation": - "IsPhysical": - "Flying": - "Buoyancy": - * */ + //m_log.DebugFormat("{0}: HandleUpdatedBucketProperties from {1}: for {2}/{3}", LogHeader, senderActorID, partUUID.ToString(), bucketName); BucketSyncInfo rBucketSyncInfo = new BucketSyncInfo(bucketName); rBucketSyncInfo.LastUpdateTimeStamp = data["LastUpdateTimeStamp"].AsLong(); @@ -1784,6 +2023,13 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule SceneObjectGroup sog = m_scene.SceneGraph.GetGroupByPrim(sogUUID); + //if this is a relay node, forwards the event + if (m_isSyncRelay) + { + SendSceneEventToRelevantSyncConnectors(senderActorID, msg, sog); + } + + if (sog != null) { if (!softDelete) @@ -1798,12 +2044,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule } } - //if this is a relay node, forwards the event - if (m_isSyncRelay) - { - //SendSceneEventToRelevantSyncConnectors(init_actorID, msg); - SendSceneEventToRelevantSyncConnectors(senderActorID, msg); - } + } private void HandleLinkObject(SymmetricSyncMessage msg, string senderActorID) @@ -1824,6 +2065,13 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule int partCount = data["partCount"].AsInteger(); List childrenIDs = new List(); + + //if this is a relay node, forwards the event + if (m_isSyncRelay) + { + SendSceneEventToRelevantSyncConnectors(senderActorID, msg, linkedGroup); + } + for (int i = 0; i < partCount; i++) { string partTempID = "part" + i; @@ -1833,18 +2081,28 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule m_log.Debug(LogHeader + " received LinkObject from " + senderActorID); //m_log.Debug("LinkedObject: " + sogxml); + //TEMP DEBUG + foreach (SceneObjectPart part in linkedGroup.Parts) + { + if (part.IsAttachment) + { + m_log.Debug(LogHeader + "HandleLinkObject: part " + part.Name + "," + part.UUID + " IsAttachment = true in incoming sync message"); + } + } + m_scene.LinkObjectBySync(linkedGroup, rootID, childrenIDs); - //if this is a relay node, forwards the event - if (m_isSyncRelay) - { - //SendSceneEventToRelevantSyncConnectors(init_actorID, msg); - SendSceneEventToRelevantSyncConnectors(senderActorID, msg); - } + } private void HandleDelinkObject(SymmetricSyncMessage msg, string senderActorID) { + //if this is a relay node, forwards the event + if (m_isSyncRelay) + { + SendSceneEventToRelevantSyncConnectors(senderActorID, msg, null); + } + OSDMap data = DeserializeMessage(msg); if (data == null) { @@ -1886,12 +2144,6 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule m_scene.DelinkObjectsBySync(delinkPrimIDs, beforeDelinkGroupIDs, incomingAfterDelinkGroups); - //if this is a relay node, forwards the event - if (m_isSyncRelay) - { - //SendSceneEventToRelevantSyncConnectors(init_actorID, msg); - SendSceneEventToRelevantSyncConnectors(senderActorID, msg); - } } /// @@ -1900,6 +2152,13 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule /// private void HandleRemoteEvent(SymmetricSyncMessage msg, string senderActorID) { + + //if this is a relay node, forwards the event + if (m_isSyncRelay) + { + SendSceneEventToRelevantSyncConnectors(senderActorID, msg, null); + } + OSDMap data = DeserializeMessage(msg); if (data == null) { @@ -1944,14 +2203,11 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule case SymmetricSyncMessage.MsgType.Attach: HandleRemoteEvent_OnAttach(init_actorID, evSeqNum, data); break; + case SymmetricSyncMessage.MsgType.PhysicsCollision: + HandleRemoteEvent_PhysicsCollision(init_actorID, evSeqNum, data); + break; } - //if this is a relay node, forwards the event - if (m_isSyncRelay) - { - //SendSceneEventToRelevantSyncConnectors(init_actorID, msg); - SendSceneEventToRelevantSyncConnectors(senderActorID, msg); - } } /// @@ -2256,7 +2512,33 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule uint localID = part.LocalId; m_scene.EventManager.TriggerOnAttachLocally(localID, itemID, avatarID); - + } + + private void HandleRemoteEvent_PhysicsCollision(string actorID, ulong evSeqNum, OSDMap data) + { + UUID primUUID = data["primUUID"].AsUUID(); + OSDArray collisionLocalIDs = (OSDArray)data["collisionLocalIDs"]; + + SceneObjectPart part = m_scene.GetSceneObjectPart(primUUID); + if (part == null) + { + m_log.WarnFormat("{0}: HandleRemoteEvent_PhysicsCollision: no part with UUID {1} found", LogHeader, primUUID); + return; + } + if (collisionLocalIDs == null) + { + m_log.WarnFormat("{0}: HandleRemoteEvent_PhysicsCollision: no collisionLocalIDs", LogHeader); + return; + } + + // Build up the collision list. The contact point is ignored so we generate some default. + CollisionEventUpdate e = new CollisionEventUpdate(); + foreach (uint collisionID in collisionLocalIDs) + { + // e.addCollider(collisionID, new ContactPoint()); + e.addCollider(collisionID, new ContactPoint(Vector3.Zero, Vector3.UnitX, 0.03f)); + } + part.PhysicsCollisionLocally(e); } /// @@ -2304,14 +2586,6 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule data["running"] = OSD.FromBoolean(isScriptRunning); data["assetID"] = OSD.FromUUID(newAssetID); - /* - data["actorID"] = OSD.FromString(m_actorID); - data["seqNum"] = OSD.FromULong(GetNextEventSeq()); - - SymmetricSyncMessage rsm = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.UpdateScript, OSDParser.SerializeJsonString(data)); - //send to actors who are interested in the event - SendSceneEventToRelevantSyncConnectors(m_actorID, rsm); - * */ SendSceneEvent(SymmetricSyncMessage.MsgType.UpdateScript, data); } @@ -2415,6 +2689,14 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule SendSceneEvent(SymmetricSyncMessage.MsgType.Attach, data); } + private void OnLocalPhysicsCollision(UUID partUUID, OSDArray collisionLocalIDs) + { + OSDMap data = new OSDMap(); + data["primUUID"] = OSD.FromUUID(partUUID); + data["collisionLocalIDs"] = collisionLocalIDs; + SendSceneEvent(SymmetricSyncMessage.MsgType.PhysicsCollision, data); + } + private void OnLocalGrabObject(uint localID, uint originalID, Vector3 offsetPos, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs) { /* @@ -2536,20 +2818,9 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule //send to actors who are interested in the event lock (m_stats) m_statEventOut++; - SendSceneEventToRelevantSyncConnectors(m_actorID, rsm); + SendSceneEventToRelevantSyncConnectors(m_actorID, rsm, null); } - /* - private void PublishSceneEvent(OSDMap data) - { - data["actorID"] = OSD.FromString(m_actorID); - data["seqNum"] = OSD.FromULong(GetNextEventSeq()); - - SymmetricSyncMessage rsm = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.OnUpdateScript, OSDParser.SerializeJsonString(data)); - SendSceneEventToRelevantSyncConnectors(m_actorID, rsm); - } - * */ - private ulong GetNextEventSeq() { return m_eventSeq++; diff --git a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/ScenePersistenceSyncModule.cs b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/ScenePersistenceSyncModule.cs index 5d6512b359..23dffef326 100755 --- a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/ScenePersistenceSyncModule.cs +++ b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/ScenePersistenceSyncModule.cs @@ -89,7 +89,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule //m_scene.EventManager.OnPostSceneCreation += OnPostSceneCreation; //Register for Scene/SceneGraph events - //m_scene.SceneGraph.OnObjectCreate += new ObjectCreateDelegate(ScenePersistence_OnObjectCreate); + m_scene.SceneGraph.OnObjectCreate += new ObjectCreateDelegate(ScenePersistence_OnObjectCreate); m_scene.SceneGraph.OnObjectCreateBySync += new ObjectCreateBySyncDelegate(ScenePersistence_OnObjectCreateBySync); } @@ -164,16 +164,33 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule /// /// ScenePersistence's actions upon an object is added to the local scene. /// - private void ScenePersistence_OnObjectCreateBySync(EntityBase entity) + private void ScenePersistence_OnObjectCreate(EntityBase entity) { if (entity is SceneObjectGroup) { - m_log.Warn(LogHeader + ": link to backup for " + entity.UUID); + //m_log.Warn(LogHeader + ":OnObjectCreate -- link to backup for " + entity.UUID); SceneObjectGroup sog = (SceneObjectGroup)entity; //probably what we should do here is to set some variable sog.SyncToBackup to true, and sog.ProcessBackup will only run if that value is true, //then we do not need to worry about where an object is attach-to-backup and modify all those lines. + sog.ToPersistObjectState = true; + sog.AttachToBackup(); + } + } + /// + /// ScenePersistence's actions upon an object is added to the local scene. + /// + private void ScenePersistence_OnObjectCreateBySync(EntityBase entity) + { + if (entity is SceneObjectGroup) + { + //m_log.Warn(LogHeader + ":OnObjectCreateBySync -- link to backup for " + entity.UUID); + SceneObjectGroup sog = (SceneObjectGroup)entity; + + //probably what we should do here is to set some variable sog.SyncToBackup to true, and sog.ProcessBackup will only run if that value is true, + //then we do not need to worry about where an object is attach-to-backup and modify all those lines. + sog.ToPersistObjectState = true; sog.AttachToBackup(); } } diff --git a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/SymmetricSyncMessage.cs b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/SymmetricSyncMessage.cs index 4775ca783c..d9b348aa85 100755 --- a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/SymmetricSyncMessage.cs +++ b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/SymmetricSyncMessage.cs @@ -47,6 +47,9 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule ObjectGrabbing, ObjectDeGrab, Attach, + PhysicsCollision, + //contorl command + SyncStateReport, } #endregion diff --git a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/SyncConnector.cs b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/SyncConnector.cs index 2ae9608991..ce9bddfc34 100755 --- a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/SyncConnector.cs +++ b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/SyncConnector.cs @@ -299,7 +299,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule //For any other messages, we simply deliver the message to RegionSyncModule for now. //Later on, we may deliver messages to different modules, say sync message to RegionSyncModule and event message to ActorSyncModule. - m_regionSyncModule.HandleIncomingMessage(msg, m_syncOtherSideActorID); + m_regionSyncModule.HandleIncomingMessage(msg, m_syncOtherSideActorID, this); } public string StatisticIdentifier() diff --git a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/SyncStatisticCollector.cs b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/SyncStatisticCollector.cs index fef5da262e..18fba4906c 100755 --- a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/SyncStatisticCollector.cs +++ b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/SyncStatisticCollector.cs @@ -1,162 +1,162 @@ -/* Copyright 2011 (c) Intel Corporation - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * The name of the copyright holder may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.IO; -using System.Text; -using System.Timers; - -namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule -{ - public interface ISyncStatistics - { - // return an identifier for this statistics source - string StatisticIdentifier(); - // a line of comma separated values - string StatisticLine(bool clearFlag); - // a line of comma separated field descriptions (describes what StatisticLine returns) - string StatisticTitle(); - } - - public class SyncStatisticCollector - { - public static bool LogEnabled = false; - public static string LogDirectory = "."; - public static int LogInterval = 5000; - public static int LogMaxFileTimeMin = 5; // 5 minutes - public static string LogFileHeader = "stats-"; - - private static List s_staters = new List(); - private static object s_statersLock = new object(); - private static Timer s_timer = null; - - static SyncStatisticCollector() - { - } - - public SyncStatisticCollector() - { - } - - /// - /// Any implementor of ISyncStatistics will call Register to put themselves in - /// the list of routines to collect statistics from. This will run periodically - /// and suck statistics from the registered routines. - /// - /// - public static void Register(ISyncStatistics stat) - { - if (!LogEnabled) return; - lock (SyncStatisticCollector.s_statersLock) - { - // set up logging timer - if (SyncStatisticCollector.s_timer == null) - { - SyncStatisticCollector.s_timer = new Timer(); - SyncStatisticCollector.s_timer.Interval = LogInterval; - SyncStatisticCollector.s_timer.Enabled = true; - SyncStatisticCollector.s_timer.Elapsed += Tick; - - } - SyncStatisticCollector.s_staters.Add(stat); - } - return; - } - - public static void Close() - { - lock (SyncStatisticCollector.s_statersLock) - { - SyncStatisticCollector.LogEnabled = false; - if (SyncStatisticCollector.s_timer != null) - { - SyncStatisticCollector.s_timer.Enabled = false; - SyncStatisticCollector.s_timer.Dispose(); - SyncStatisticCollector.s_timer = null; - } - if (SyncStatisticCollector.LogFile != null) - { - SyncStatisticCollector.LogFile.Close(); - SyncStatisticCollector.LogFile.Dispose(); - SyncStatisticCollector.LogFile = null; - } - } - } - - - private static void Tick(object sender, EventArgs e) - { - if (!LogEnabled) return; - lock (SyncStatisticCollector.s_statersLock) - { - foreach (ISyncStatistics iss in s_staters) - { - LogWriter(iss.StatisticIdentifier() + "," + iss.StatisticLine(true)); - } - } - return; - } - - private static DateTime LogStartTime; - private static System.IO.TextWriter LogFile = null; - private static void LogWriter(string line) - { - try - { - DateTime now = DateTime.Now; - if (LogFile == null || (now > (LogStartTime + new TimeSpan(0, LogMaxFileTimeMin, 0)))) - { - if (LogFile != null) - { - LogFile.Close(); - LogFile.Dispose(); - LogFile = null; - } - - // First log file or time has expired, start writing to a new log file - LogStartTime = now; - string path = (LogDirectory.Length > 0 ? LogDirectory - + System.IO.Path.DirectorySeparatorChar.ToString() : "") - + String.Format("{0}{1}.log", LogFileHeader, now.ToString("yyyyMMddHHmmss")); - LogFile = new StreamWriter(File.Open(path, FileMode.Append, FileAccess.Write)); - } - if (LogFile != null) - { - StringBuilder buff = new StringBuilder(); - // buff.Append(now.ToString("yyyyMMddHHmmssfff")); - buff.Append(now.ToString("yyyyMMddHHmmss")); - buff.Append(","); - buff.Append(line); - buff.Append("\r\n"); - LogFile.Write(buff.ToString()); - } - } - catch (Exception e) - { - // m_log.ErrorFormat("{0}: FAILURE WRITING TO LOGFILE: {1}", LogHeader, e); - LogEnabled = false; - } - return; - } - } -} +/* Copyright 2011 (c) Intel Corporation + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * The name of the copyright holder may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Timers; + +namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule +{ + public interface ISyncStatistics + { + // return an identifier for this statistics source + string StatisticIdentifier(); + // a line of comma separated values + string StatisticLine(bool clearFlag); + // a line of comma separated field descriptions (describes what StatisticLine returns) + string StatisticTitle(); + } + + public class SyncStatisticCollector + { + public static bool LogEnabled = false; + public static string LogDirectory = "."; + public static int LogInterval = 5000; + public static int LogMaxFileTimeMin = 5; // 5 minutes + public static string LogFileHeader = "stats-"; + + private static List s_staters = new List(); + private static object s_statersLock = new object(); + private static Timer s_timer = null; + + static SyncStatisticCollector() + { + } + + public SyncStatisticCollector() + { + } + + /// + /// Any implementor of ISyncStatistics will call Register to put themselves in + /// the list of routines to collect statistics from. This will run periodically + /// and suck statistics from the registered routines. + /// + /// + public static void Register(ISyncStatistics stat) + { + if (!LogEnabled) return; + lock (SyncStatisticCollector.s_statersLock) + { + // set up logging timer + if (SyncStatisticCollector.s_timer == null) + { + SyncStatisticCollector.s_timer = new Timer(); + SyncStatisticCollector.s_timer.Interval = LogInterval; + SyncStatisticCollector.s_timer.Enabled = true; + SyncStatisticCollector.s_timer.Elapsed += Tick; + + } + SyncStatisticCollector.s_staters.Add(stat); + } + return; + } + + public static void Close() + { + lock (SyncStatisticCollector.s_statersLock) + { + SyncStatisticCollector.LogEnabled = false; + if (SyncStatisticCollector.s_timer != null) + { + SyncStatisticCollector.s_timer.Enabled = false; + SyncStatisticCollector.s_timer.Dispose(); + SyncStatisticCollector.s_timer = null; + } + if (SyncStatisticCollector.LogFile != null) + { + SyncStatisticCollector.LogFile.Close(); + SyncStatisticCollector.LogFile.Dispose(); + SyncStatisticCollector.LogFile = null; + } + } + } + + + private static void Tick(object sender, EventArgs e) + { + if (!LogEnabled) return; + lock (SyncStatisticCollector.s_statersLock) + { + foreach (ISyncStatistics iss in s_staters) + { + LogWriter(iss.StatisticIdentifier() + "," + iss.StatisticLine(true)); + } + } + return; + } + + private static DateTime LogStartTime; + private static System.IO.TextWriter LogFile = null; + private static void LogWriter(string line) + { + try + { + DateTime now = DateTime.Now; + if (LogFile == null || (now > (LogStartTime + new TimeSpan(0, LogMaxFileTimeMin, 0)))) + { + if (LogFile != null) + { + LogFile.Close(); + LogFile.Dispose(); + LogFile = null; + } + + // First log file or time has expired, start writing to a new log file + LogStartTime = now; + string path = (LogDirectory.Length > 0 ? LogDirectory + + System.IO.Path.DirectorySeparatorChar.ToString() : "") + + String.Format("{0}{1}.log", LogFileHeader, now.ToString("yyyyMMddHHmmss")); + LogFile = new StreamWriter(File.Open(path, FileMode.Append, FileAccess.Write)); + } + if (LogFile != null) + { + StringBuilder buff = new StringBuilder(); + // buff.Append(now.ToString("yyyyMMddHHmmssfff")); + buff.Append(now.ToString("yyyyMMddHHmmss")); + buff.Append(","); + buff.Append(line); + buff.Append("\r\n"); + LogFile.Write(buff.ToString()); + } + } + catch (Exception e) + { + // m_log.ErrorFormat("{0}: FAILURE WRITING TO LOGFILE: {1}", LogHeader, e); + LogEnabled = false; + } + return; + } + } +} diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index 9d83bba6b3..ebd120208c 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -60,7 +60,7 @@ namespace OpenSim.Region.Framework.Scenes ObjectGrabbing, ObjectDeGrab, Attach, //attaching object to avatar - + PhysicsCollision, } public EventManager(Scene scene) diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 6d086d6844..c1ea8a3340 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -2203,6 +2203,13 @@ namespace OpenSim.Region.Framework.Scenes partnames += "(" + part.Name + ", " + part.UUID + ")"; } m_log.DebugFormat("[SCENE] RezObject {0} with InvItem name {1} at pos {2} with parts {3}", group.UUID.ToString(), item.Name, group.RootPart.GroupPosition.ToString(), partnames); + foreach (SceneObjectPart part in group.Parts) + { + if (part.IsAttachment) + { + m_log.Debug("[SCENE]: part " + part.Name + "," + part.UUID + ", IsAttachment = true"); + } + } // We can only call this after adding the scene object, since the scene object references the scene // to find out if scripts should be activated at all. diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 941988f750..12a31b5f56 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -684,6 +684,28 @@ namespace OpenSim.Region.Framework.Scenes return m_sceneGraph.AddOrUpdateObjectBySynchronization(sog); } + public ObjectUpdateResult UpdateObjectBySynchronization(SceneObjectGroup sog) + { + return m_sceneGraph.UpdateObjectBySynchronization(sog); + } + + public void DeleteAllSceneObjectsBySync() + { + lock (Entities) + { + EntityBase[] entities = Entities.GetEntities(); + foreach (EntityBase e in entities) + { + if (e is SceneObjectGroup) + { + SceneObjectGroup sog = (SceneObjectGroup)e; + if (!sog.IsAttachment) + DeleteSceneObjectBySynchronization((SceneObjectGroup)e); + } + } + } + } + //Similar to DeleteSceneObject, except that this does not change LastUpdateActorID and LastUpdateTimeStamp public void DeleteSceneObjectBySynchronization(SceneObjectGroup group) { @@ -732,12 +754,12 @@ namespace OpenSim.Region.Framework.Scenes m_sceneGraph.AddNewSceneObjectPart(newPart, parentGroup); } - public void AddNewSceneObjectBySync(SceneObjectGroup group, bool attachToBackup) + public ObjectUpdateResult AddNewSceneObjectBySync(SceneObjectGroup group) { - if(attachToBackup) - group.HasGroupChanged = true; + //if(attachToBackup) + // group.HasGroupChanged = true; - m_sceneGraph.AddSceneObjectByStateSynch(group); + return m_sceneGraph.AddNewSceneObjectBySync(group); } public void DebugSceneObjectGroups() @@ -795,7 +817,12 @@ namespace OpenSim.Region.Framework.Scenes } //m_log.Debug("to link part " + part.DebugObjectPartProperties()); - m_log.Debug("to link part " + part.Name + "," + part.UUID + "; its SOG has " + part.ParentGroup.Parts + " parts"); + string partNames = ""; + foreach (SceneObjectPart child in part.ParentGroup.Parts) + { + partNames += "(" + child.Name + "," + child.UUID + ")"; + } + m_log.Debug("LinkObjectBySync: " + part.Name + "," + part.UUID + " with root "+root.Name+","+root.UUID+"; its SOG has " + part.ParentGroup.Parts.Length + " parts : "+partNames); children.Add(part); } @@ -805,7 +832,13 @@ namespace OpenSim.Region.Framework.Scenes //Leverage the LinkObject implementation to get the book keeping of Group and Parts relations right m_sceneGraph.LinkObjectsBySync(root, children); - + foreach (SceneObjectPart part in linkedGroup.Parts) + { + if (part.IsAttachment) + { + m_log.Debug("LinkObjectBySync: part " + part.Name + "," + part.UUID + " IsAttachment = true after linking"); + } + } //The properties of the newly linked object should be updated later with another UpdatedObject message. diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 52913f66a1..3534179f31 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -2002,6 +2002,37 @@ namespace OpenSim.Region.Framework.Scenes #region SYMMETRIC SYNC + public Scene.ObjectUpdateResult UpdateObjectBySynchronization(SceneObjectGroup updatedSog) + { + UUID sogID = updatedSog.UUID; + Scene.ObjectUpdateResult updateResult = Scene.ObjectUpdateResult.Unchanged; + + if (Entities.ContainsKey(sogID)) + { + //update the object + EntityBase entity = Entities[sogID]; + if (entity is SceneObjectGroup) + { + SceneObjectGroup localSog = (SceneObjectGroup)entity; + updateResult = localSog.UpdateObjectGroupBySync(updatedSog); + } + else + { + m_log.WarnFormat("{0}: Entity with {1} is not of type SceneObjectGroup: {2}", + "[SCENE GRAPH]", sogID, entity.GetType().ToString()); + //return false; + updateResult = Scene.ObjectUpdateResult.Error; + } + } + else + { + //An object no longer in Entity list, probably linked to other objects, or handed over to another quark. + m_log.WarnFormat("[SCENE GRAPH] UpdateObjectBySynchronization: received update for an object {0}, {1} no longer in local Entity list. Ignore update.", updatedSog.Name, updatedSog.UUID); + } + + return updateResult; + } + public Scene.ObjectUpdateResult AddOrUpdateObjectBySynchronization(SceneObjectGroup updatedSog) { UUID sogID = updatedSog.UUID; @@ -2026,8 +2057,8 @@ namespace OpenSim.Region.Framework.Scenes } else { - m_log.Debug(updatedSog.Name+" "+updatedSog.UUID+" not found in Entities list. Need to add"); - AddSceneObjectByStateSynch(updatedSog); + //m_log.Debug(updatedSog.Name+" "+updatedSog.UUID+" not found in Entities list. Need to add"); + AddNewSceneObjectBySync(updatedSog); updateResult = Scene.ObjectUpdateResult.New; } @@ -2040,13 +2071,18 @@ namespace OpenSim.Region.Framework.Scenes //This is called when an object is added due to receiving a state synchronization message from Scene or an actor. Do similar things as the original AddSceneObject(), //but call ScheduleGroupForFullUpdate_TimeStampUnchanged() instead, so as not to modify the timestamp or actorID, since the object was not created locally. - public bool AddSceneObjectByStateSynch(SceneObjectGroup sceneObject) + public Scene.ObjectUpdateResult AddNewSceneObjectBySync(SceneObjectGroup sceneObject) { + Scene.ObjectUpdateResult updateResult = Scene.ObjectUpdateResult.New; + if (sceneObject == null || sceneObject.RootPart == null || sceneObject.RootPart.UUID == UUID.Zero) - return false; + return Scene.ObjectUpdateResult.Error; if (Entities.ContainsKey(sceneObject.UUID)) - return false; + { + m_log.WarnFormat("[SCENE GRAPH] AddNewSceneObjectBySync: Already has object {0}, {1} in local Entity list.", sceneObject.Name, sceneObject.UUID); + return Scene.ObjectUpdateResult.Error; + } SceneObjectPart[] children = sceneObject.Parts; @@ -2070,8 +2106,6 @@ namespace OpenSim.Region.Framework.Scenes } m_numPrim += children.Length; - m_log.Debug("Attached obj " + sceneObject.Name + "," + sceneObject.UUID + " to Scene"); - sceneObject.AttachToScene(m_parentScene); //Take some special care of the case of this object being an attachment @@ -2113,7 +2147,7 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectGroupsByLocalID[part.LocalId] = sceneObject; } - return true; + return updateResult; } public void AddNewSceneObjectPart(SceneObjectPart newPart, SceneObjectGroup parentGroup) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index a3ec2ecedf..a1fde883ec 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -1372,6 +1372,14 @@ namespace OpenSim.Region.Framework.Scenes return; } + //SYMMETRIC SYNC + //if we are doing sync across different sync nodes, and are not told to persist the state, don't do anything (only persistence actor will do it) + if (m_scene.RegionSyncModule != null && !ToPersistObjectState) + { + return; + } + //end of SYMMETRIC SYNC + // Since this is the top of the section of call stack for backing up a particular scene object, don't let // any exception propogate upwards. try @@ -2113,9 +2121,9 @@ namespace OpenSim.Region.Framework.Scenes // objectGroup.RootPart.SendScheduledUpdates(); //} - // m_log.DebugFormat( - // "[SCENE OBJECT GROUP]: Linking group with root part {0}, {1} to group with root part {2}, {3}", - // objectGroup.RootPart.Name, objectGroup.RootPart.UUID, RootPart.Name, RootPart.UUID); + m_log.DebugFormat( + "[SCENE OBJECT GROUP]: Linking group with root part {0}, {1} to group with root part {2}, {3}", + objectGroup.RootPart.Name, objectGroup.RootPart.UUID, RootPart.Name, RootPart.UUID); SceneObjectPart linkPart = objectGroup.m_rootPart; @@ -3556,6 +3564,13 @@ namespace OpenSim.Region.Framework.Scenes #region SYMMETRIC SYNC + private bool m_toPersistObjectState = false; + public bool ToPersistObjectState + { + get { return m_toPersistObjectState; } + set { m_toPersistObjectState = value; } + } + //update the existing copy of the object with updated properties in 'updatedSog' //NOTE: updates on script content are handled seperately (e.g. user edited the script and saved it) -- SESyncServerOnUpdateScript(), a handler of EventManager.OnUpdateScript //public void UpdateObjectProperties(SceneObjectGroup updatedSog) @@ -3847,7 +3862,7 @@ namespace OpenSim.Region.Framework.Scenes bool newGroupBySync = true; SceneObjectGroup objectGroup = new SceneObjectGroup(delinkPart, newGroupBySync); - m_scene.AddNewSceneObjectBySync(objectGroup, true); + m_scene.AddNewSceneObjectBySync(objectGroup); if (sendEvents) linkPart.TriggerScriptChangedEvent(Changed.LINK); diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index e6aaf408cd..ad5c3ae5ff 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -2202,7 +2202,7 @@ namespace OpenSim.Region.Framework.Scenes { } - public void PhysicsCollision(EventArgs e) + public virtual void PhysicsCollision(EventArgs e) { // single threaded here if (e == null) @@ -2795,6 +2795,7 @@ namespace OpenSim.Region.Framework.Scenes m_parentGroup.AbsolutePosition = newpos; return; } + // m_log.DebugFormat("[PHYSICS]: TerseUpdate: UUID={0}, newpos={1}", PhysActor.UUID.ToString(), newpos.ToString()); //m_parentGroup.RootPart.m_groupPosition = newpos; } @@ -5003,7 +5004,8 @@ namespace OpenSim.Region.Framework.Scenes //lock for concurrent updates of the timestamp and actorID. private Object m_updateLock = new Object(); private string m_bucketName; - private bool m_bucketTainted = false; + private bool m_bucketLocallyTainted = false; //indicating if the bucket has been tainted by local write operations + private bool m_bucketTaintedBySync = false; //indicating if the bucket has been tainted by remote write operations (propogated by synchronization) public long LastUpdateTimeStamp { @@ -5022,9 +5024,14 @@ namespace OpenSim.Region.Framework.Scenes get { return m_bucketName; } } - public bool Tainted + public bool LocallyTainted { - get { return m_bucketTainted; } + get { return m_bucketLocallyTainted; } + } + + public bool TaintedBySync + { + get { return m_bucketTaintedBySync; } } public BucketSyncInfo(string bucketName) @@ -5045,17 +5052,27 @@ namespace OpenSim.Region.Framework.Scenes { m_lastUpdateTimeStamp = timeStamp; m_lastUpdateActorID = actorID; - m_bucketTainted = false; //clear taint + m_bucketLocallyTainted = false; //clear taint } } - public void TaintBucket() + public void TaintBucketLocally() { lock (m_updateLock) { - m_bucketTainted = true; + m_bucketLocallyTainted = true; } } + + public void TaintBucketBySync() + { + m_bucketTaintedBySync = true; + } + + public void ClearBucketTaintBySync() + { + m_bucketTaintedBySync = false; + } } /* @@ -5462,6 +5479,8 @@ namespace OpenSim.Region.Framework.Scenes localPart.TextureAnimation = updatedPart.TextureAnimation; localPart.ParticleSystem = updatedPart.ParticleSystem; + bool preIsAttachment = localPart.IsAttachment; + if (!localPart.AttachedAvatar.Equals(updatedPart.AttachedAvatar)) { localPart.AttachedAvatar = updatedPart.AttachedAvatar; @@ -5477,7 +5496,13 @@ namespace OpenSim.Region.Framework.Scenes // localPart.IsAttachment = updatedPart.IsAttachment; //} + if (localPart.IsAttachment) + { + m_log.Debug("GeneralBucketUpdateProcessor: part " + localPart.Name + "," + localPart.UUID + ", IsAttachment = true; previously, IsAttachment = " + preIsAttachment.ToString()); + } + localPart.AggregateScriptEvents = updatedPart.AggregateScriptEvents; + aggregateScriptEventSubscriptions(); m_bucketSyncInfoList[bucketName].LastUpdateTimeStamp = updatedPart.BucketSyncInfoList[bucketName].LastUpdateTimeStamp; m_bucketSyncInfoList[bucketName].LastUpdateActorID = updatedPart.BucketSyncInfoList[bucketName].LastUpdateActorID; @@ -5496,9 +5521,41 @@ namespace OpenSim.Region.Framework.Scenes //NOTE: Passing null argument to make sure that LastUpdateTimeStamp and LastUpdateActorID of each bucket // are kept the same as in the received copy of the object. ScheduleFullUpdate(null); - + + //Mark the bucket as having been tainted by sync operations + m_bucketSyncInfoList[bucketName].TaintBucketBySync(); } + // Do any subscriptions based on the AggregateScriptEvents + protected void aggregateScriptEventSubscriptions() + { + if ( + ((AggregateScriptEvents & scriptEvents.collision) != 0) || + ((AggregateScriptEvents & scriptEvents.collision_end) != 0) || + ((AggregateScriptEvents & scriptEvents.collision_start) != 0) || + ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) || + ((AggregateScriptEvents & scriptEvents.land_collision) != 0) || + ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) || + (CollisionSound != UUID.Zero) + ) + { + // subscribe to physics updates. + if (PhysActor != null) + { + PhysActor.OnCollisionUpdate += PhysicsCollision; + PhysActor.SubscribeEvents(1000); + + } + } + else + { + if (PhysActor != null) + { + PhysActor.UnSubscribeEvents(); + PhysActor.OnCollisionUpdate -= PhysicsCollision; + } + } + } //NOTE: only touch the properties and BucketSyncInfo that is related to the given bucketName. Other properties and //buckets may not be filled at all in "updatedPart". @@ -5540,7 +5597,10 @@ namespace OpenSim.Region.Framework.Scenes localPart.AngularVelocity = data["AngularVelocity"].AsVector3(); localPart.RotationOffset = data["RotationOffset"].AsQuaternion(); - if (pa != null) + //m_log.Debug("Received Physics Bucket updates for " + localPart.Name + ","+localPart.UUID + // + ". GroupPosition: " + data["GroupPosition"].AsVector3().ToString()); + + if (pa != null && data.ContainsKey("PA_Acceleration")) { pa.Size = data["Size"].AsVector3(); pa.Position = data["Position"].AsVector3(); @@ -5556,6 +5616,8 @@ namespace OpenSim.Region.Framework.Scenes pa.Buoyancy = (float)data["Buoyancy"].AsReal(); pa.CollidingGround = data["CollidingGround"].AsBoolean(); pa.IsColliding = data["IsColliding"].AsBoolean(); + + // m_log.DebugFormat("{0}: PhysicsBucketUpdateProcessor for {2},{3}. pos={1}", , data["Position"].AsVector3().ToString(), localPart.Name, localPart.UUID); } m_bucketSyncInfoList[bucketName].LastUpdateTimeStamp = data["LastUpdateTimeStamp"].AsLong(); @@ -5571,7 +5633,9 @@ namespace OpenSim.Region.Framework.Scenes // are kept the same as in the received copy of the object. ScheduleFullUpdate(null); - + + //Mark the bucket as having been tainted by sync operations + m_bucketSyncInfoList[bucketName].TaintBucketBySync(); } //Initialize and set the values of timestamp and actorID for each synchronization bucket. @@ -5626,7 +5690,7 @@ namespace OpenSim.Region.Framework.Scenes { foreach (BucketSyncInfo bucketSynInfo in m_bucketSyncInfoList.Values) { - bucketSynInfo.TaintBucket(); + bucketSynInfo.TaintBucketLocally(); } // m_log.DebugFormat("{0}: TaintBucketSyncInfo: FullUpdate", "[SCENE OBJECT PART]"); } @@ -5634,7 +5698,10 @@ namespace OpenSim.Region.Framework.Scenes { string bucketName = m_primPropertyBucketMap[property]; //m_bucketSyncTainted[bucketName] = true; - m_bucketSyncInfoList[bucketName].TaintBucket(); + m_bucketSyncInfoList[bucketName].TaintBucketLocally(); + + // m_log.Debug(this.Name + ": " + property.ToString() + " just changed. Tainted " + bucketName); + // m_log.DebugFormat("{0}: TaintBucketSyncInfo: tainting bucket {1} for {2}", // "[SCENE OBJECT PART]", bucketName, property.ToString()); } @@ -5642,11 +5709,15 @@ namespace OpenSim.Region.Framework.Scenes } - public bool HasPropertyUpdatedLocallyInGivenBucket(string bucketName) + public bool HasPropertyUpdatedLocally(string bucketName) { - return m_bucketSyncInfoList[bucketName].Tainted; + return m_bucketSyncInfoList[bucketName].LocallyTainted; } + public bool HasPropertyUpdatedBySync(string bucketName) + { + return m_bucketSyncInfoList[bucketName].TaintedBySync; + } /// /// Update the timestamp information of each property bucket, and clear out the taint on each bucket. @@ -5659,7 +5730,7 @@ namespace OpenSim.Region.Framework.Scenes foreach (KeyValuePair pair in m_bucketSyncInfoList) { string bucketName = pair.Key; - if (m_bucketSyncInfoList[bucketName].Tainted) + if (m_bucketSyncInfoList[bucketName].LocallyTainted) { m_bucketSyncInfoList[bucketName].UpdateSyncInfoAndClearTaint(timeStamp, m_localActorID); } @@ -5680,7 +5751,7 @@ namespace OpenSim.Region.Framework.Scenes foreach (KeyValuePair pair in m_bucketSyncInfoList) { string bucketName = pair.Key; - if (m_bucketSyncInfoList[bucketName].Tainted) + if (m_bucketSyncInfoList[bucketName].LocallyTainted) { m_bucketSyncInfoList[bucketName].UpdateSyncInfoAndClearTaint(timeStamp, m_localActorID); } @@ -5692,7 +5763,7 @@ namespace OpenSim.Region.Framework.Scenes { if (m_syncEnabled) { - if (m_bucketSyncInfoList[bucketName].Tainted) + if (m_bucketSyncInfoList[bucketName].LocallyTainted) { m_bucketSyncInfoList[bucketName].UpdateSyncInfoAndClearTaint(timeStamp, m_localActorID); } @@ -5767,8 +5838,10 @@ namespace OpenSim.Region.Framework.Scenes { if (!m_bucketSyncInfoList[bucketName].LastUpdateActorID.Equals(updatedPart.BucketSyncInfoList[bucketName].LastUpdateActorID)) { - m_log.Warn("Different actors modified SceneObjetPart " + UUID + " with the same TimeStamp (" + m_bucketSyncInfoList[bucketName].LastUpdateActorID - + "," + updatedPart.BucketSyncInfoList[bucketName].LastUpdateActorID + ", CONFLICT RESOLUTION TO BE IMPLEMENTED, PICK A WINNER!!!!"); + m_log.Warn("Different actors modified SceneObjetPart " + Name+"," +UUID + ", bucket "+bucketName+", with the same TimeStamp (" + + m_bucketSyncInfoList[bucketName].LastUpdateActorID + + "," + updatedPart.BucketSyncInfoList[bucketName].LastUpdateActorID + + ", CONFLICT RESOLUTION TO BE IMPLEMENTED, PICK A WINNER!!!!"); } //TODO: conflict resolution to be implemented -- pick a winner continue; @@ -5821,8 +5894,10 @@ namespace OpenSim.Region.Framework.Scenes { if (!m_bucketSyncInfoList[bucketName].LastUpdateActorID.Equals(rBucketSyncInfo.LastUpdateActorID)) { - m_log.Warn("Different actors modified SceneObjetPart " + UUID + " with the same TimeStamp (" + m_bucketSyncInfoList[bucketName].LastUpdateActorID - + "," + rBucketSyncInfo.LastUpdateActorID + ", CONFLICT RESOLUTION TO BE IMPLEMENTED, PICK A WINNER!!!!"); + m_log.Warn("UpdateBucketProperties: Different actors modified SceneObjetPart " + Name + "," + UUID + ", bucket " + bucketName + ", with the same TimeStamp (" + + m_bucketSyncInfoList[bucketName].LastUpdateActorID + + "," + rBucketSyncInfo.LastUpdateActorID + + ", CONFLICT RESOLUTION TO BE IMPLEMENTED, PICK A WINNER!!!!"); } //TODO: conflict resolution to be implemented -- pick a winner return partUpdateResult; @@ -5907,6 +5982,30 @@ namespace OpenSim.Region.Framework.Scenes } return false; } + + public override void PhysicsCollision(EventArgs e) + { + if (m_parentGroup.Scene.RegionSyncModule != null) + { + CollisionEventUpdate a = (CollisionEventUpdate)e; + Dictionary collisionswith = a.m_objCollisionList; + OSDArray collisionLocalIDs = new OSDArray(); + foreach (uint collisionObject in collisionswith.Keys) + { + collisionLocalIDs.Add(collisionObject); + } + object[] eventArgs = new object[2]; + eventArgs[0] = this.UUID; + eventArgs[1] = collisionLocalIDs; + m_parentGroup.Scene.RegionSyncModule.PublishSceneEvent(EventManager.EventNames.PhysicsCollision, eventArgs); + } + PhysicsCollisionLocally(e); + } + + public void PhysicsCollisionLocally(EventArgs e) + { + base.PhysicsCollision(e); + } } //end of SYMMETRIC SYNC