From 2bea8bb4bc19c8b2d840bc3eb20a621b3a5e51c3 Mon Sep 17 00:00:00 2001 From: "Huaiyu (Kitty) Liu" Date: Wed, 6 Apr 2011 12:23:04 -0700 Subject: [PATCH] Added class PropertySyncInfo and PrimSyncInfo in RegionSyncModule. --- .../SymmetricSync/RegionSyncModule.cs | 282 ++++++++++-------- .../Framework/Interfaces/IRegionSyncModule.cs | 5 +- 2 files changed, 166 insertions(+), 121 deletions(-) diff --git a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs index 10a510d96a..184bd4e000 100644 --- a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs +++ b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs @@ -130,27 +130,6 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule //Called after AddRegion() has been called for all region modules of the scene public void RegionLoaded(Scene scene) { - //m_log.Warn(LogHeader + " RegionLoaded() called"); - - /* - //If this one is configured to start a listener so that other actors can connect to form a overlay, start the listener. - //For now, we use the star topology, and ScenePersistence actor is always the one to start the listener. - if (m_isSyncListenerLocal) - { - StartLocalSyncListener(); - } - else - { - //Start connecting to the remote listener. TO BE IMPLEMENTED. - //For now, the connection will be started by manually typing in "sync start". - - } - * */ - - //Start symmetric synchronization initialization automatically - //SyncStart(null); - - // connect to statistics system SyncStatisticCollector.Register(this); } @@ -182,24 +161,20 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule // Synchronization related members and functions, exposed through IRegionSyncModule interface /////////////////////////////////////////////////////////////////////////////////////////////////// - private DSGActorTypes m_actorType = DSGActorTypes.Unknown; - /// - /// The type of the actor running locally. This value will be set by an ActorSyncModule, so that - /// no hard code needed in RegionSyncModule to recoganize the actor's type, thus make it easier - /// to add new ActorSyncModules w/o chaning the code in RegionSyncModule. - /// - public DSGActorTypes DSGActorType - { - get { return m_actorType; } - set { m_actorType = value; } - } - + //ActorID might not be in use anymore. Rather, SyncID should be used. + //(Synchronization is sync node centric, not actor centric.) private string m_actorID; public string ActorID { get { return m_actorID; } } + private string m_syncID; + public string SyncID + { + get { return m_syncID; } + } + private bool m_active = false; public bool Active { @@ -228,12 +203,10 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule foreach (string bucketName in m_propertyBucketNames) { - //if (m_isSyncRelay || part.HasPropertyUpdatedLocallyInGivenBucket(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+" at pos "+part.GroupPosition.ToString()); m_primUpdates[bucketName][part.UUID] = part; } } @@ -250,8 +223,11 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule } - + //SendSceneUpdates put each update into an outgoing queue of each SyncConnector + /// + /// Send updates to other sync nodes. So far we only handle object updates. + /// public void SendSceneUpdates() { if (!IsSyncingWithOtherSyncNodes()) @@ -271,7 +247,6 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule return; } - //List primUpdates=null; Dictionary> primUpdates = new Dictionary>(); bool updated = false; @@ -304,18 +279,6 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule } } - List presenceUpdates = new List(); - /* - if (m_presenceUpdates.Count > 0) - { - lock (m_updateScenePresenceLock) - { - updated = true; - presenceUpdates = new List(m_presenceUpdates.Values); - m_presenceUpdates.Clear(); - } - } - */ if (updated) { @@ -337,48 +300,6 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule primUpdates[bucketName].Clear(); } } - foreach (ScenePresence presence in presenceUpdates) - { - try - { - if (!presence.IsDeleted) - { - /* - OSDMap data = new OSDMap(10); - data["id"] = OSD.FromUUID(presence.UUID); - // Do not include offset for appearance height. That will be handled by RegionSyncClient before sending to viewers - if(presence.AbsolutePosition.IsFinite()) - data["pos"] = OSD.FromVector3(presence.AbsolutePosition); - else - data["pos"] = OSD.FromVector3(Vector3.Zero); - if(presence.Velocity.IsFinite()) - data["vel"] = OSD.FromVector3(presence.Velocity); - else - data["vel"] = OSD.FromVector3(Vector3.Zero); - data["rot"] = OSD.FromQuaternion(presence.Rotation); - data["fly"] = OSD.FromBoolean(presence.Flying); - data["flags"] = OSD.FromUInteger((uint)presence.AgentControlFlags); - data["anim"] = OSD.FromString(presence.Animator.CurrentMovementAnimation); - // needed for a full update - if (presence.ParentID != presence.lastSentParentID) - { - data["coll"] = OSD.FromVector4(presence.CollisionPlane); - data["off"] = OSD.FromVector3(presence.OffsetPosition); - data["pID"] = OSD.FromUInteger(presence.ParentID); - presence.lastSentParentID = presence.ParentID; - } - - RegionSyncMessage rsm = new RegionSyncMessage(RegionSyncMessage.MsgType.UpdatedAvatar, OSDParser.SerializeJsonString(data)); - m_server.EnqueuePresenceUpdate(presence.UUID, rsm.ToBytes()); - */ - - } - } - catch (Exception e) - { - m_log.ErrorFormat("[REGION SYNC MODULE] Caught exception sending presence updates for {0}: {1}", presence.Name, e); - } - } // Indicate that the current batch of updates has been completed Interlocked.Exchange(ref m_sendingUpdates, 0); @@ -583,21 +504,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule OnLocalScriptReset((uint)evArgs[0], (UUID)evArgs[1]); return; case EventManager.EventNames.ChatFromClient: - /*if (evArgs.Length < 2) - { - m_log.Error(LogHeader + " not enough event args for ChatFromClient"); - return; - } - OnLocalChatFromClient(evArgs[0], (OSChatMessage)evArgs[1]); - return;*/ - case EventManager.EventNames.ChatFromWorld: - /*if (evArgs.Length < 2) - { - m_log.Error(LogHeader + " not enough event args for ChatFromWorld"); - return; - } - OnLocalChatFromWorld(evArgs[0], (OSChatMessage)evArgs[1]); - return;*/ + case EventManager.EventNames.ChatFromWorld: case EventManager.EventNames.ChatBroadcast: if (evArgs.Length < 2) { @@ -699,9 +606,9 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule #region RegionSyncModule members and functions - ///////////////////////////////////////////////////////////////////////////////////////// - // Synchronization related functions, NOT exposed through IRegionSyncModule interface - ///////////////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + // Memeber variables + /////////////////////////////////////////////////////////////////////// private static int PortUnknown = -1; private static string IPAddrUnknown = String.Empty; @@ -740,9 +647,16 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule private RegionSyncListener m_localSyncListener = null; private bool m_synced = false; - // Lock is used to synchronize access to the update status and update queues - //private object m_updateSceneObjectPartLock = new object(); - //private Dictionary m_primUpdates = new Dictionary(); + /////////////////////////////////////////////////////////////////////// + // Memeber variables for per-property timestamp + /////////////////////////////////////////////////////////////////////// + + + + /////////////////////////////////////////////////////////////////////// + // Legacy members for bucket-based sync, + /////////////////////////////////////////////////////////////////////// + private Dictionary m_primUpdateLocks = new Dictionary(); private Dictionary> m_primUpdates = new Dictionary>(); @@ -771,6 +685,10 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule private int m_maxNumOfPropertyBuckets; + ///////////////////////////////////////////////////////////////////////////////////////// + // Synchronization related functions, NOT exposed through IRegionSyncModule interface + ///////////////////////////////////////////////////////////////////////////////////////// + private void StatsTimerElapsed(object source, System.Timers.ElapsedEventArgs e) { //TO BE IMPLEMENTED @@ -1690,7 +1608,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule m_log.Error(LogHeader + "interface Scene.ActorSyncModule has not been set yet"); return; } - m_actorType = m_scene.ActorSyncModule.ActorType; + //m_actorType = m_scene.ActorSyncModule.ActorType; } //Start symmetric synchronization initialization automatically @@ -1800,12 +1718,6 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule //Start SyncListener if a listener is supposed to run on this actor; Otherwise, initiate connections to remote listeners. private void SyncStart(Object[] args) { - if (m_actorType == DSGActorTypes.Unknown) - { - m_log.Error(LogHeader + ": SyncStart -- ActorType not set yet. Either it's not defined in config file (DSGActorType), or the ActorSyncModule (ScenePersistenceSyncModule, ScriptEngineSyncModule etc) has not defined it."); - return; - } - if (m_isSyncListenerLocal) { if (m_localSyncListener!=null && m_localSyncListener.IsListening) @@ -3400,5 +3312,137 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule } } + + /////////////////////////////////////////////////////////////////////////// + // + /////////////////////////////////////////////////////////////////////////// + + public enum PropertyUpdateSource + { + Local, + BySync + } + + public class PropertySyncInfo + { + private ulong m_lastUpdateTimeStamp; + public ulong LastUpdateTimeStamp + { + get { return m_lastUpdateTimeStamp; } + } + + private string m_lastUpdateSyncID; + public string LastUpdateSyncID + { + get { return m_lastUpdateSyncID; } + } + + /// + /// The value of the most recent value sent/received by Sync Module. + /// For property with simple types, the value is copied directly. + /// For property with complex data structures, the value (values of + /// subproperties) is serialized and stored. + /// + private Object m_lastUpdateValue; + public Object LastUpdateValue + { + get { return m_lastUpdateValue; } + } + + /// + /// Record the time the last sync message about this property is received. + /// This value is only meaninful when m_lastUpdateSource==BySync + /// + private ulong m_lastSyncUpdateRecvTime; + public ulong LastSyncUpdateRecvTime + { + get { return m_lastSyncUpdateRecvTime; } + set { m_lastSyncUpdateRecvTime = value; } + } + + private PropertyUpdateSource m_lastUpdateSource; + public PropertyUpdateSource LastUpdateSource + { + get { return m_lastUpdateSource; } + } + + private Object m_syncInfoLock = new Object(); + + /// + /// Update SyncInfo when the property is updated locally. + /// + /// the time + /// + public void UpdateSyncInfoLocally(ulong ts, string syncID, Object pValue) + { + lock (m_syncInfoLock) + { + m_lastUpdateValue = pValue; + m_lastUpdateTimeStamp = ts; + m_lastUpdateSyncID = syncID; + m_lastUpdateSource = PropertyUpdateSource.Local; + } + } + + /// + /// Update SyncInfo when the property is updated by receiving a sync + /// message. + /// + /// + /// + public void UpdateSyncInfoBySync(ulong ts, string syncID, ulong recvTS, Object pValue) + { + lock (m_syncInfoLock) + { + m_lastUpdateValue = pValue; + m_lastUpdateTimeStamp = ts; + m_lastUpdateSyncID = syncID; + m_lastSyncUpdateRecvTime = recvTS; + m_lastUpdateSource = PropertyUpdateSource.BySync; + } + } + } + + public class PrimSyncInfo + { + #region Members + public static long TimeOutThreshold; + + private Dictionary m_propertiesSyncInfo; + public Dictionary PropertiesSyncInfo + { + get { return m_propertiesSyncInfo; } + } + + private ulong m_PrimLastUpdateTime; + public ulong PrimLastUpdateTime + { + get { return m_PrimLastUpdateTime; } + } + #endregion //Members + + #region Constructor + public PrimSyncInfo() + { + m_propertiesSyncInfo = new Dictionary(); + + foreach (SceneObjectPartProperties property in Enum.GetValues(typeof(SceneObjectPartProperties))) + { + PropertySyncInfo syncInfo = new PropertySyncInfo(); + m_propertiesSyncInfo.Add(property, syncInfo); + } + } + #endregion //Constructor + + public void UpdatePropertySyncInfoLocally(SceneObjectPartProperties property, ulong lastUpdateTS, string syncID, Object pValue) + { + m_propertiesSyncInfo[property].UpdateSyncInfoLocally(lastUpdateTS, syncID, pValue); + } + + public void UpdatePropertySyncInfoBySync(SceneObjectPartProperties property, ulong lastUpdateTS, string syncID, Object pValue, ulong recvTS) + { + m_propertiesSyncInfo[property].UpdateSyncInfoBySync(lastUpdateTS, syncID, recvTS, pValue); + } + } } diff --git a/OpenSim/Region/Framework/Interfaces/IRegionSyncModule.cs b/OpenSim/Region/Framework/Interfaces/IRegionSyncModule.cs index 891e6761fd..667bf46276 100755 --- a/OpenSim/Region/Framework/Interfaces/IRegionSyncModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IRegionSyncModule.cs @@ -52,8 +52,9 @@ namespace OpenSim.Region.Framework.Interfaces public interface IRegionSyncModule { bool Active { get; } //if true, this RegionSyncModule is connected into the synchronization overlay - string ActorID { get; } - DSGActorTypes DSGActorType { get; set; } + string ActorID { get; } //might be phased out soon + string SyncID { get; } + //DSGActorTypes DSGActorType { get; set; } bool IsSyncRelay { get; } ///