check in updates in enabling bucket based synchronization.
parent
a7d4c974dd
commit
97b01dcf75
|
@ -19,6 +19,8 @@ using System.Net.Sockets;
|
|||
using System.Threading;
|
||||
using System.Text;
|
||||
|
||||
using System.IO;
|
||||
using System.Xml;
|
||||
using Mono.Addins;
|
||||
using OpenMetaverse.StructuredData;
|
||||
|
||||
|
@ -61,6 +63,9 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
|||
m_isSyncRelay = m_sysConfig.GetBoolean("IsSyncRelay", false);
|
||||
m_isSyncListenerLocal = m_sysConfig.GetBoolean("IsSyncListenerLocal", false);
|
||||
|
||||
//Setup the PropertyBucketMap
|
||||
PupolatePropertyBucketMap(m_sysConfig);
|
||||
|
||||
m_active = true;
|
||||
|
||||
LogHeader += "-Actor " + m_actorID;
|
||||
|
@ -176,6 +181,17 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
|||
get { return m_isSyncRelay; }
|
||||
}
|
||||
|
||||
private Dictionary<string, string> m_primPropertyBucketMap = new Dictionary<string, string>();
|
||||
public Dictionary<string, string> PrimPropertyBucketMap
|
||||
{
|
||||
get { return m_primPropertyBucketMap; }
|
||||
}
|
||||
private List<string> m_propertyBucketDescription = new List<string>();
|
||||
public List<string> PropertyBucketDescription
|
||||
{
|
||||
get { return m_propertyBucketDescription; }
|
||||
}
|
||||
|
||||
private RegionSyncListener m_localSyncListener = null;
|
||||
private bool m_synced = false;
|
||||
|
||||
|
@ -184,7 +200,64 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
|||
private Dictionary<UUID, SceneObjectGroup> m_primUpdates = new Dictionary<UUID, SceneObjectGroup>();
|
||||
private object m_updateScenePresenceLock = new object();
|
||||
private Dictionary<UUID, ScenePresence> m_presenceUpdates = new Dictionary<UUID, ScenePresence>();
|
||||
private int m_sendingUpdates;
|
||||
private int m_sendingUpdates=0;
|
||||
|
||||
private int m_maxNumOfPropertyBuckets;
|
||||
|
||||
//Read in configuration for which property-bucket each property belongs to, and the description of each bucket
|
||||
private void PupolatePropertyBucketMap(IConfig config)
|
||||
{
|
||||
//We start with a default bucket map. Will add the code to read in configuration from config files later.
|
||||
PupolatePropertyBuketMapByDefault();
|
||||
|
||||
//Pass the bucket information to SceneObjectPart.
|
||||
SceneObjectPart.InitializeBucketInfo(m_primPropertyBucketMap, m_propertyBucketDescription, m_actorID);
|
||||
|
||||
}
|
||||
|
||||
//If nothing configured in the config file, this is the default settings for grouping properties into different bucket
|
||||
private void PupolatePropertyBuketMapByDefault()
|
||||
{
|
||||
//by default, there are two property buckets: the "General" bucket and the "Physics" bucket.
|
||||
string generalBucketName = "General";
|
||||
string physicsBucketName = "Physics";
|
||||
m_propertyBucketDescription.Add(generalBucketName);
|
||||
m_propertyBucketDescription.Add(physicsBucketName);
|
||||
m_maxNumOfPropertyBuckets = 2;
|
||||
|
||||
foreach (string pName in SceneObjectPart.PropertyList)
|
||||
{
|
||||
switch (pName){
|
||||
case "GroupPosition":
|
||||
case "OffsetPosition":
|
||||
case "Scale":
|
||||
case "Velocity":
|
||||
case "AngularVelocity":
|
||||
case "RotationOffset":
|
||||
case "Position":
|
||||
case "Size":
|
||||
case "Force":
|
||||
case "RotationalVelocity":
|
||||
case "PA_Acceleration":
|
||||
case "Torque":
|
||||
case "Orientation":
|
||||
case "IsPhysical":
|
||||
case "Flying":
|
||||
case "Buoyancy":
|
||||
m_primPropertyBucketMap.Add(pName, physicsBucketName);
|
||||
break;
|
||||
default:
|
||||
//all other properties belong to the "General" bucket.
|
||||
m_primPropertyBucketMap.Add(pName, generalBucketName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsSyncingWithOtherActors()
|
||||
{
|
||||
return (m_syncConnectors.Count > 0);
|
||||
}
|
||||
|
||||
public void QueueSceneObjectPartForUpdate(SceneObjectPart part)
|
||||
{
|
||||
|
@ -209,6 +282,12 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
|||
//SendSceneUpdates put each update into an outgoing queue of each SyncConnector
|
||||
public void SendSceneUpdates()
|
||||
{
|
||||
if (!IsSyncingWithOtherActors())
|
||||
{
|
||||
//no SyncConnector connected. Do nothing.
|
||||
return;
|
||||
}
|
||||
|
||||
// Existing value of 1 indicates that updates are currently being sent so skip updates this pass
|
||||
if (Interlocked.Exchange(ref m_sendingUpdates, 1) == 1)
|
||||
{
|
||||
|
@ -323,6 +402,11 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
|||
|
||||
public void SendTerrainUpdates(string lastUpdateActorID)
|
||||
{
|
||||
if (!IsSyncingWithOtherActors())
|
||||
{
|
||||
//no SyncConnector connected. Do nothing.
|
||||
return;
|
||||
}
|
||||
if(m_isSyncRelay || m_actorID.Equals(lastUpdateActorID))
|
||||
{
|
||||
//m_scene.Heightmap should have been updated already by the caller, send it out
|
||||
|
@ -340,7 +424,13 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
|||
//private void RegionSyncModule_OnObjectBeingRemovedFromScene(SceneObjectGroup sog)
|
||||
public void SendDeleteObject(SceneObjectGroup sog, bool softDelete)
|
||||
{
|
||||
m_log.DebugFormat("SendDeleteObject called for object {0}", sog.UUID);
|
||||
if (!IsSyncingWithOtherActors())
|
||||
{
|
||||
//no SyncConnector connected. Do nothing.
|
||||
return;
|
||||
}
|
||||
|
||||
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))
|
||||
|
@ -362,6 +452,12 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
|||
{
|
||||
if(children.Count==0) return;
|
||||
|
||||
if (!IsSyncingWithOtherActors())
|
||||
{
|
||||
//no SyncConnector connected. Do nothing.
|
||||
return;
|
||||
}
|
||||
|
||||
OSDMap data = new OSDMap();
|
||||
string sogxml = SceneObjectSerializer.ToXml2Format(linkedGroup);
|
||||
data["linkedGroup"]=OSD.FromString(sogxml);
|
||||
|
@ -383,6 +479,12 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
|||
{
|
||||
if (prims.Count==0 || beforeDelinkGroups.Count==0) return;
|
||||
|
||||
if (!IsSyncingWithOtherActors())
|
||||
{
|
||||
//no SyncConnector connected. Do nothing.
|
||||
return;
|
||||
}
|
||||
|
||||
OSDMap data = new OSDMap();
|
||||
data["partCount"] = OSD.FromInteger(prims.Count);
|
||||
int partNum = 0;
|
||||
|
@ -420,6 +522,12 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
|||
|
||||
public void PublishSceneEvent(EventManager.EventNames ev, Object[] evArgs)
|
||||
{
|
||||
if (!IsSyncingWithOtherActors())
|
||||
{
|
||||
//no SyncConnector connected. Do nothing.
|
||||
return;
|
||||
}
|
||||
|
||||
switch (ev)
|
||||
{
|
||||
case EventManager.EventNames.NewScript:
|
||||
|
@ -500,9 +608,13 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
|||
|
||||
Command cmdSyncStatus = new Command("status", CommandIntentions.COMMAND_HAZARDOUS, SyncStatus, "Displays synchronization status.");
|
||||
|
||||
//for debugging purpose
|
||||
Command cmdSyncDebug = new Command("debug", CommandIntentions.COMMAND_HAZARDOUS, SyncDebug, "Trigger some debugging functions");
|
||||
|
||||
m_commander.RegisterCommand("start", cmdSyncStart);
|
||||
m_commander.RegisterCommand("stop", cmdSyncStop);
|
||||
m_commander.RegisterCommand("status", cmdSyncStatus);
|
||||
m_commander.RegisterCommand("debug", cmdSyncDebug);
|
||||
|
||||
lock (m_scene)
|
||||
{
|
||||
|
@ -864,6 +976,38 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
|||
m_log.Warn("[REGION SYNC MODULE]: SyncStatus() TO BE IMPLEMENTED !!!");
|
||||
}
|
||||
|
||||
private void SyncDebug(Object[] args)
|
||||
{
|
||||
if (m_scene != null)
|
||||
{
|
||||
EntityBase[] entities = m_scene.GetEntities();
|
||||
foreach (EntityBase entity in entities)
|
||||
{
|
||||
if (entity is SceneObjectGroup)
|
||||
{
|
||||
//first test serialization
|
||||
StringWriter sw = new StringWriter();
|
||||
XmlTextWriter writer = new XmlTextWriter(sw);
|
||||
Dictionary<string, BucketSyncInfo> bucketSyncInfoList = new Dictionary<string,BucketSyncInfo>();
|
||||
BucketSyncInfo generalBucket = new BucketSyncInfo(DateTime.Now.Ticks, m_actorID, "General");
|
||||
bucketSyncInfoList.Add("General", generalBucket);
|
||||
BucketSyncInfo physicsBucket = new BucketSyncInfo(DateTime.Now.Ticks, m_actorID, "Physics");
|
||||
bucketSyncInfoList.Add("Physics", physicsBucket);
|
||||
SceneObjectSerializer.WriteBucketSyncInfo(writer, bucketSyncInfoList);
|
||||
|
||||
string xmlString = sw.ToString();
|
||||
m_log.Debug("Serialized xml string: " + xmlString);
|
||||
|
||||
//second, test de-serialization
|
||||
XmlTextReader reader = new XmlTextReader(new StringReader(xmlString));
|
||||
SceneObjectPart part = new SceneObjectPart();
|
||||
SceneObjectSerializer.ProcessBucketSyncInfo(part, reader);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Start connections to each remote listener.
|
||||
//For now, there is only one remote listener.
|
||||
private bool StartSyncConnections()
|
||||
|
|
|
@ -110,7 +110,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.WarnFormat("{0} [Start] Could not connect to RegionSyncServer at {1}:{2}", LogHeader, m_remoteListenerInfo.Addr, m_remoteListenerInfo.Port);
|
||||
m_log.WarnFormat("{0} [Start] Could not connect to RegionSyncModule at {1}:{2}", LogHeader, m_remoteListenerInfo.Addr, m_remoteListenerInfo.Port);
|
||||
m_log.Warn(e.Message);
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -579,6 +579,15 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
// Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled
|
||||
// for the same object with very different properties. The caller must schedule the update.
|
||||
//ScheduleGroupForFullUpdate();
|
||||
|
||||
//SYMMETRIC SYNC
|
||||
if (m_scene.RegionSyncModule != null)
|
||||
{
|
||||
foreach (SceneObjectPart part in Parts)
|
||||
{
|
||||
part.InitializeBucketSyncInfo();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Vector3 GroupScale()
|
||||
|
|
|
@ -107,6 +107,56 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
|
||||
#endregion Enumerations
|
||||
|
||||
//SYMMETRIC SYNC
|
||||
|
||||
//Information for concurrency control of one bucket of prim proproperties.
|
||||
public class BucketSyncInfo
|
||||
{
|
||||
private long m_lastUpdateTimeStamp;
|
||||
private string m_lastUpdateActorID;
|
||||
//lock for concurrent updates of the timestamp and actorID.
|
||||
private Object m_updateLock = new Object();
|
||||
private string m_bucketName;
|
||||
|
||||
public long LastUpdateTimeStamp
|
||||
{
|
||||
get { return m_lastUpdateTimeStamp; }
|
||||
}
|
||||
|
||||
public string LastUpdateActorID
|
||||
{
|
||||
get { return m_lastUpdateActorID; }
|
||||
}
|
||||
|
||||
public string BucketName
|
||||
{
|
||||
get { return m_bucketName; }
|
||||
}
|
||||
|
||||
public BucketSyncInfo(string bucketName)
|
||||
{
|
||||
m_bucketName = bucketName;
|
||||
}
|
||||
|
||||
public BucketSyncInfo(long timeStamp, string actorID, string bucketName)
|
||||
{
|
||||
m_lastUpdateTimeStamp = timeStamp;
|
||||
m_lastUpdateActorID = actorID;
|
||||
m_bucketName = bucketName;
|
||||
}
|
||||
|
||||
public void UpdateSyncInfo(long timeStamp, string actorID)
|
||||
{
|
||||
lock (m_updateLock)
|
||||
{
|
||||
m_lastUpdateTimeStamp = timeStamp;
|
||||
m_lastUpdateActorID = actorID;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
//end of SYMMETRIC SYNC
|
||||
|
||||
public class SceneObjectPart : IScriptHost, ISceneEntity
|
||||
{
|
||||
/// <value>
|
||||
|
@ -127,7 +177,23 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
|
||||
#region Fields
|
||||
|
||||
public bool AllowedDrop;
|
||||
//SYMMETRIC SYNC
|
||||
//public bool AllowedDrop;
|
||||
private bool m_allowedDrop;
|
||||
public bool AllowedDrop
|
||||
{
|
||||
get { return m_allowedDrop; }
|
||||
set
|
||||
{
|
||||
//m_allowedDrop = value;
|
||||
SetAllowedDrop(value);
|
||||
UpdateBucketSyncInfo("AllowedDrop");
|
||||
}
|
||||
}
|
||||
public void SetAllowedDrop(bool value)
|
||||
{
|
||||
m_allowedDrop = value;
|
||||
}
|
||||
|
||||
|
||||
public bool DIE_AT_EDGE;
|
||||
|
@ -731,6 +797,57 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
return m_groupPosition;
|
||||
}
|
||||
set
|
||||
{
|
||||
SetGroupPosition(value);
|
||||
UpdateBucketSyncInfo("GroupPosition");
|
||||
|
||||
/*
|
||||
//Legacy Opensim code
|
||||
m_groupPosition = value;
|
||||
|
||||
PhysicsActor actor = PhysActor;
|
||||
if (actor != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Root prim actually goes at Position
|
||||
if (_parentID == 0)
|
||||
{
|
||||
actor.Position = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
// To move the child prim in respect to the group position and rotation we have to calculate
|
||||
actor.Position = GetWorldPosition();
|
||||
actor.Orientation = GetWorldRotation();
|
||||
}
|
||||
|
||||
// Tell the physics engines that this prim changed.
|
||||
m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO if we decide to do sitting in a more SL compatible way (multiple avatars per prim), this has to be fixed, too
|
||||
if (m_sitTargetAvatar != UUID.Zero)
|
||||
{
|
||||
if (m_parentGroup != null) // TODO can there be a SOP without a SOG?
|
||||
{
|
||||
ScenePresence avatar;
|
||||
if (m_parentGroup.Scene.TryGetScenePresence(m_sitTargetAvatar, out avatar))
|
||||
{
|
||||
avatar.ParentPosition = GetWorldPosition();
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
//SYMMETRIC SYNC
|
||||
public void SetGroupPosition(Vector3 value)
|
||||
{
|
||||
m_groupPosition = value;
|
||||
|
||||
|
@ -773,13 +890,16 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Vector3 OffsetPosition
|
||||
{
|
||||
get { return m_offsetPosition; }
|
||||
set
|
||||
{
|
||||
SetOffsetPosition(value);
|
||||
UpdateBucketSyncInfo("OffsetPosition");
|
||||
/*
|
||||
StoreUndoState();
|
||||
m_offsetPosition = value;
|
||||
|
||||
|
@ -795,6 +915,26 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
|
||||
}
|
||||
}
|
||||
* */
|
||||
}
|
||||
}
|
||||
//SYMMETRIC SYNC
|
||||
public void SetOffsetPosition(Vector3 value)
|
||||
{
|
||||
StoreUndoState();
|
||||
m_offsetPosition = value;
|
||||
|
||||
if (ParentGroup != null && !ParentGroup.IsDeleted)
|
||||
{
|
||||
PhysicsActor actor = PhysActor;
|
||||
if (_parentID != 0 && actor != null)
|
||||
{
|
||||
actor.Position = GetWorldPosition();
|
||||
actor.Orientation = GetWorldRotation();
|
||||
|
||||
// Tell the physics engines that this prim changed.
|
||||
m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -836,6 +976,9 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
|
||||
set
|
||||
{
|
||||
SetRotationOffset(value);
|
||||
UpdateBucketSyncInfo("RotationOffset");
|
||||
/*
|
||||
StoreUndoState();
|
||||
m_rotationOffset = value;
|
||||
|
||||
|
@ -865,9 +1008,43 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
m_log.Error("[SCENEOBJECTPART]: ROTATIONOFFSET" + ex.Message);
|
||||
}
|
||||
}
|
||||
* */
|
||||
|
||||
}
|
||||
}
|
||||
//SYMMETRIC SYNC
|
||||
public void SetRotationOffset(Quaternion value)
|
||||
{
|
||||
StoreUndoState();
|
||||
m_rotationOffset = value;
|
||||
|
||||
PhysicsActor actor = PhysActor;
|
||||
if (actor != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Root prim gets value directly
|
||||
if (_parentID == 0)
|
||||
{
|
||||
actor.Orientation = value;
|
||||
//m_log.Info("[PART]: RO1:" + actor.Orientation.ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Child prim we have to calculate it's world rotationwel
|
||||
Quaternion resultingrotation = GetWorldRotation();
|
||||
actor.Orientation = resultingrotation;
|
||||
//m_log.Info("[PART]: RO2:" + actor.Orientation.ToString());
|
||||
}
|
||||
m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
|
||||
//}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
m_log.Error("[SCENEOBJECTPART]: ROTATIONOFFSET" + ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary></summary>
|
||||
public Vector3 Velocity
|
||||
|
@ -888,6 +1065,9 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
|
||||
set
|
||||
{
|
||||
SetVelocity(value);
|
||||
UpdateBucketSyncInfo("Velocity");
|
||||
/*
|
||||
m_velocity = value;
|
||||
|
||||
PhysicsActor actor = PhysActor;
|
||||
|
@ -899,6 +1079,22 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
|
||||
}
|
||||
}
|
||||
* */
|
||||
}
|
||||
}
|
||||
//SYMMETRIC SYNC
|
||||
public void SetVelocity(Vector3 value)
|
||||
{
|
||||
m_velocity = value;
|
||||
|
||||
PhysicsActor actor = PhysActor;
|
||||
if (actor != null)
|
||||
{
|
||||
if (actor.IsPhysical)
|
||||
{
|
||||
actor.Velocity = value;
|
||||
m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -914,7 +1110,17 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
}
|
||||
return m_angularVelocity;
|
||||
}
|
||||
set { m_angularVelocity = value; }
|
||||
set
|
||||
{
|
||||
SetAngularVelocity(value);
|
||||
UpdateBucketSyncInfo("AngularVelocity");
|
||||
//m_angularVelocity = value;
|
||||
}
|
||||
}
|
||||
//SYMMETRIC SYNC
|
||||
public void SetAngularVelocity(Vector3 value)
|
||||
{
|
||||
m_angularVelocity = value;
|
||||
}
|
||||
|
||||
/// <summary></summary>
|
||||
|
@ -1010,6 +1216,34 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
{
|
||||
get { return m_shape.Scale; }
|
||||
set
|
||||
{
|
||||
SetScale(value);
|
||||
UpdateBucketSyncInfo("Scale");
|
||||
/*
|
||||
StoreUndoState();
|
||||
if (m_shape != null)
|
||||
{
|
||||
m_shape.Scale = value;
|
||||
|
||||
PhysicsActor actor = PhysActor;
|
||||
if (actor != null && m_parentGroup != null)
|
||||
{
|
||||
if (m_parentGroup.Scene != null)
|
||||
{
|
||||
if (m_parentGroup.Scene.PhysicsScene != null)
|
||||
{
|
||||
actor.Size = m_shape.Scale;
|
||||
m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
TriggerScriptChangedEvent(Changed.SCALE);
|
||||
* */
|
||||
}
|
||||
}
|
||||
//SYMMETRIC SYNC
|
||||
public void SetScale(Vector3 value)
|
||||
{
|
||||
StoreUndoState();
|
||||
if (m_shape != null)
|
||||
|
@ -1031,7 +1265,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
}
|
||||
TriggerScriptChangedEvent(Changed.SCALE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public byte UpdateFlag
|
||||
{
|
||||
|
@ -4971,10 +5205,88 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
}
|
||||
}
|
||||
|
||||
//The list of each prim's properties. This is the list of properties that matter in synchronizing prim copies on different actors.
|
||||
//This list is created based on properties included in the serialization/deserialization process (see SceneObjectSerializer()) and the
|
||||
//properties Physics Engine needs to synchronize to other actors.
|
||||
public static List<string> PropertyList = new List<string>()
|
||||
{
|
||||
//Following properties copied from SceneObjectSerializer()
|
||||
"AllowedDrop",
|
||||
"CreatorID",
|
||||
"CreatorData",
|
||||
"FolderID",
|
||||
"InventorySerial",
|
||||
"TaskInventory",
|
||||
"UUID",
|
||||
"LocalId",
|
||||
"Name",
|
||||
"Material",
|
||||
"PassTouches",
|
||||
"RegionHandle",
|
||||
"ScriptAccessPin",
|
||||
"GroupPosition",
|
||||
"OffsetPosition",
|
||||
"RotationOffset",
|
||||
"Velocity",
|
||||
"AngularVelocity",
|
||||
//"Acceleration",
|
||||
"SOP_Acceleration", //SOP and PA read/write their own local copies of acceleration, so we distinguish the copies
|
||||
"Description",
|
||||
"Color",
|
||||
"Text",
|
||||
"SitName",
|
||||
"TouchName",
|
||||
"LinkNum",
|
||||
"ClickAction",
|
||||
"Shape",
|
||||
"Scale",
|
||||
"UpdateFlag",
|
||||
"SitTargetOrientation",
|
||||
"SitTargetPosition",
|
||||
"SitTargetPositionLL",
|
||||
"SitTargetOrientationLL",
|
||||
"ParentID",
|
||||
"CreationDate",
|
||||
"Category",
|
||||
"SalePrice",
|
||||
"ObjectSaleType",
|
||||
"OwnershipCost",
|
||||
"GroupID",
|
||||
"OwnerID",
|
||||
"LastOwnerID",
|
||||
"BaseMask",
|
||||
"OwnerMask",
|
||||
"GroupMask",
|
||||
"EveryoneMask",
|
||||
"NextOwnerMask",
|
||||
"Flags",
|
||||
"CollisionSound",
|
||||
"CollisionSoundVolume",
|
||||
"MediaUrl",
|
||||
"TextureAnimation",
|
||||
"ParticleSystem",
|
||||
//Property names below copied from PhysicsActor, they are necessary in synchronization, but not covered the above properties
|
||||
//Physics properties "Velocity" is covered above
|
||||
"Position",
|
||||
"Size",
|
||||
"Force",
|
||||
"RotationalVelocity",
|
||||
"PA_Acceleration",
|
||||
"Torque",
|
||||
"Orientation",
|
||||
"IsPhysical",
|
||||
"Flying",
|
||||
"Buoyancy",
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
private Object propertyUpdateLock = new Object();
|
||||
|
||||
//!!!!!! -- TODO:
|
||||
//!!!!!! -- We should call UpdateXXX functions to update each property, cause some of such updates involves sanity checking.
|
||||
|
||||
public Scene.ObjectUpdateResult UpdateAllProperties(SceneObjectPart updatedPart)
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -5098,6 +5410,8 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
return partUpdateResult;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private bool UpdateCollisionSound(UUID updatedCollisionSound)
|
||||
{
|
||||
if (this.CollisionSound != updatedCollisionSound)
|
||||
|
@ -5150,6 +5464,197 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
|
||||
}
|
||||
|
||||
//The following variables should be initialized when this SceneObjectPart is added into the local Scene.
|
||||
//private List<BucketSyncInfo> SynchronizeUpdatesToScene = null;
|
||||
//public List<BucketSyncInfo> BucketSyncInfoList
|
||||
private Dictionary<string, BucketSyncInfo> m_bucketSyncInfoList = new Dictionary<string, BucketSyncInfo>();
|
||||
public Dictionary<string, BucketSyncInfo> BucketSyncInfoList
|
||||
{
|
||||
get { return m_bucketSyncInfoList; }
|
||||
set { m_bucketSyncInfoList = value; }
|
||||
}
|
||||
//TODO: serialization and deserialization processors to be added in SceneObjectSerializer
|
||||
|
||||
//The following variables are initialized when RegionSyncModule reads the config file for mapping of properties and buckets
|
||||
private static Dictionary<string, string> m_primPropertyBucketMap = null;
|
||||
private static List<string> m_propertyBucketNames = null;
|
||||
//private static List<Object> m_bucketUpdateLocks = null;
|
||||
private static Dictionary<string, Object> m_bucketUpdateLocks = new Dictionary<string, object>();
|
||||
|
||||
private static string m_localActorID = "";
|
||||
//private static int m_bucketCount = 0;
|
||||
//private delegate void BucketUpdateProcessor(int bucketIndex);
|
||||
private delegate void BucketUpdateProcessor(string bucketName);
|
||||
|
||||
private static Dictionary<string, BucketUpdateProcessor> m_bucketUpdateProcessors = new Dictionary<string, BucketUpdateProcessor>();
|
||||
|
||||
public static void InitializeBucketInfo(Dictionary<string, string> propertyBucketMap, List<string> bucketNames, string actorID)
|
||||
{
|
||||
m_primPropertyBucketMap = propertyBucketMap;
|
||||
m_propertyBucketNames = bucketNames;
|
||||
m_localActorID = actorID;
|
||||
//m_bucketCount = bucketNames.Count;
|
||||
|
||||
RegisterBucketUpdateProcessor();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Link each bucket with the function that applies updates to properties in the bucket. This is the "hard-coded" part
|
||||
/// in the property-buckets implementation. When new buckets are implemented, the processing functions need to be modified accordingly.
|
||||
/// </summary>
|
||||
private static void RegisterBucketUpdateProcessor()
|
||||
{
|
||||
foreach (string bucketName in m_propertyBucketNames)
|
||||
{
|
||||
switch (bucketName)
|
||||
{
|
||||
case "General":
|
||||
m_bucketUpdateProcessors.Add(bucketName, GeneralBucketUpdateProcessor);
|
||||
break;
|
||||
case "Physics":
|
||||
m_bucketUpdateProcessors.Add(bucketName, PhysicsBucketUpdateProcessor);
|
||||
break;
|
||||
default:
|
||||
m_log.Warn("Bucket " + bucketName + "'s update processing function not defined yet");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void GeneralBucketUpdateProcessor(string bucketName)
|
||||
{
|
||||
lock (m_bucketUpdateLocks[bucketName])
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private static void PhysicsBucketUpdateProcessor(string bucketName)
|
||||
{
|
||||
lock (m_bucketUpdateLocks[bucketName])
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//Initialize and set the values of timestamp and actorID for each synchronization bucket.
|
||||
//Should be called when the SceneObjectGroup this part is in is added to scene, see SceneObjectGroup.AttachToScene.
|
||||
public void InitializeBucketSyncInfo()
|
||||
{
|
||||
if (m_primPropertyBucketMap == null)
|
||||
{
|
||||
m_log.Error("Bucket Information has not been initilized. Return.");
|
||||
return;
|
||||
}
|
||||
long timeStamp = DateTime.Now.Ticks;
|
||||
|
||||
m_log.Debug("InitializeBucketSyncInfo called at " + timeStamp);
|
||||
|
||||
for (int i = 0; i < m_propertyBucketNames.Count; i++)
|
||||
{
|
||||
string bucketName = m_propertyBucketNames[i];
|
||||
BucketSyncInfo syncInfo = new BucketSyncInfo(timeStamp, m_localActorID, bucketName);
|
||||
|
||||
//If the object is created by de-serialization, then it already has m_bucketSyncInfoList populated with the right number of buckets
|
||||
if (m_bucketSyncInfoList.ContainsKey(bucketName))
|
||||
{
|
||||
m_bucketSyncInfoList[bucketName] = syncInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_bucketSyncInfoList.Add(bucketName, syncInfo);
|
||||
}
|
||||
if (!m_bucketSyncInfoList.ContainsKey(bucketName))
|
||||
{
|
||||
m_bucketUpdateLocks.Add(bucketName, new Object());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update the timestamp and actorID information of the bucket the given property belongs to.
|
||||
/// </summary>
|
||||
/// <param name="propertyName">Name of the property. Make sure the spelling is consistent with what are defined in PropertyList</param>
|
||||
private void UpdateBucketSyncInfo(string propertyName)
|
||||
{
|
||||
if (m_bucketSyncInfoList != null && m_bucketSyncInfoList.Count>0)
|
||||
{
|
||||
//int bucketIndex = m_primPropertyBucketMap[propertyName];
|
||||
string bucketName = m_primPropertyBucketMap[propertyName];
|
||||
long timeStamp = DateTime.Now.Ticks;
|
||||
if (m_bucketSyncInfoList.ContainsKey(bucketName))
|
||||
{
|
||||
m_bucketSyncInfoList[bucketName].UpdateSyncInfo(timeStamp, m_localActorID);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_log.Warn("No SyncInfo of bucket (name: " + bucketName + ") found");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
||||
public Scene.ObjectUpdateResult UpdateAllProperties(SceneObjectPart updatedPart)
|
||||
{
|
||||
|
||||
////////////////////Assumptions: ////////////////////
|
||||
//(1) prim's UUID and LocalID shall not change (UUID is the unique identifies, LocalID is used to refer to the prim by, say scripts)
|
||||
//(2) RegionHandle won't be updated -- each copy of Scene is hosted on a region with different region handle
|
||||
//(3) ParentID won't be updated -- if the rootpart of the SceneObjectGroup changed, that will be updated in SceneObjectGroup.UpdateObjectProperties
|
||||
|
||||
////////////////////Furture enhancements:////////////////////
|
||||
//For now, we only update the set of properties that are included in serialization, and some PhysicsActor properties
|
||||
//See RegionSyncModule.PupolatePropertyBuketMapByDefault for the properties that are handled.
|
||||
|
||||
if (updatedPart == null)
|
||||
return Scene.ObjectUpdateResult.Error;
|
||||
|
||||
//Compate the timestamp of each bucket and update the properties if needed
|
||||
|
||||
Scene.ObjectUpdateResult partUpdateResult = Scene.ObjectUpdateResult.Unchanged;
|
||||
|
||||
for (int i=0; i<m_bucketCount; i++){
|
||||
string bucketName = m_propertyBucketNames[i];
|
||||
//First, compare the bucket's timestamp and actorID
|
||||
if (m_bucketSyncInfoList[bucketName].LastUpdateTimeStamp > updatedPart.BucketSyncInfoList[bucketName].LastUpdateTimeStamp)
|
||||
{
|
||||
//Our timestamp is more update to date, keep our values of the properties. Do not update anything.
|
||||
continue;
|
||||
}
|
||||
|
||||
if (m_bucketSyncInfoList[bucketName].LastUpdateTimeStamp == updatedPart.BucketSyncInfoList[bucketName].LastUpdateTimeStamp)
|
||||
{
|
||||
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!!!!");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
//Second, if need to update local properties, call each bucket's update process
|
||||
if (m_bucketUpdateProcessors.ContainsKey(bucketName))
|
||||
{
|
||||
m_bucketUpdateProcessors[bucketName](bucketName);
|
||||
partUpdateResult = Scene.ObjectUpdateResult.Updated;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_log.Warn("No update processor for property bucket " + bucketName);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
return partUpdateResult;
|
||||
|
||||
}
|
||||
*/
|
||||
//private void UpdateBucketProperties(string bucketDescription,
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
|
|
@ -332,6 +332,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
|
|||
//SYMMETRIC SYNC
|
||||
m_SOPXmlProcessors.Add("LastUpdateTimeStamp", ProcessUpdateTimeStamp);
|
||||
m_SOPXmlProcessors.Add("LastUpdateActorID", ProcessLastUpdateActorID);
|
||||
m_SOPXmlProcessors.Add("BucketSyncInfoList", ProcessBucketSyncInfo);
|
||||
//end of SYMMETRIC SYNC
|
||||
|
||||
#endregion
|
||||
|
@ -417,9 +418,12 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
|
|||
}
|
||||
|
||||
#region SOPXmlProcessors
|
||||
//SYMMETRIC SYNC NOTE: -- assignments in de-serialization should directly set the values w/o triggering SceneObjectPart.UpdateBucketSyncInfo;
|
||||
//That is, calling SetXXX(value) instead of using "XXX = value".
|
||||
private static void ProcessAllowedDrop(SceneObjectPart obj, XmlTextReader reader)
|
||||
{
|
||||
obj.AllowedDrop = Util.ReadBoolean(reader);
|
||||
//obj.AllowedDrop = Util.ReadBoolean(reader);
|
||||
obj.SetAllowedDrop(Util.ReadBoolean(reader));
|
||||
}
|
||||
|
||||
private static void ProcessCreatorID(SceneObjectPart obj, XmlTextReader reader)
|
||||
|
@ -484,27 +488,32 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
|
|||
|
||||
private static void ProcessGroupPosition(SceneObjectPart obj, XmlTextReader reader)
|
||||
{
|
||||
obj.GroupPosition = Util.ReadVector(reader, "GroupPosition");
|
||||
//obj.GroupPosition = Util.ReadVector(reader, "GroupPosition");
|
||||
obj.SetGroupPosition(Util.ReadVector(reader, "GroupPosition"));
|
||||
}
|
||||
|
||||
private static void ProcessOffsetPosition(SceneObjectPart obj, XmlTextReader reader)
|
||||
{
|
||||
obj.OffsetPosition = Util.ReadVector(reader, "OffsetPosition"); ;
|
||||
//obj.OffsetPosition = Util.ReadVector(reader, "OffsetPosition"); ;
|
||||
obj.SetOffsetPosition(Util.ReadVector(reader, "OffsetPosition"));
|
||||
}
|
||||
|
||||
private static void ProcessRotationOffset(SceneObjectPart obj, XmlTextReader reader)
|
||||
{
|
||||
obj.RotationOffset = Util.ReadQuaternion(reader, "RotationOffset");
|
||||
//obj.RotationOffset = Util.ReadQuaternion(reader, "RotationOffset");
|
||||
obj.SetRotationOffset(Util.ReadQuaternion(reader, "RotationOffset"));
|
||||
}
|
||||
|
||||
private static void ProcessVelocity(SceneObjectPart obj, XmlTextReader reader)
|
||||
{
|
||||
obj.Velocity = Util.ReadVector(reader, "Velocity");
|
||||
//obj.Velocity = Util.ReadVector(reader, "Velocity");
|
||||
obj.SetVelocity(Util.ReadVector(reader, "Velocity"));
|
||||
}
|
||||
|
||||
private static void ProcessAngularVelocity(SceneObjectPart obj, XmlTextReader reader)
|
||||
{
|
||||
obj.AngularVelocity = Util.ReadVector(reader, "AngularVelocity");
|
||||
//obj.AngularVelocity = Util.ReadVector(reader, "AngularVelocity");
|
||||
obj.SetVelocity(Util.ReadVector(reader, "AngularVelocity"));
|
||||
}
|
||||
|
||||
private static void ProcessAcceleration(SceneObjectPart obj, XmlTextReader reader)
|
||||
|
@ -563,7 +572,8 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
|
|||
|
||||
private static void ProcessScale(SceneObjectPart obj, XmlTextReader reader)
|
||||
{
|
||||
obj.Scale = Util.ReadVector(reader, "Scale");
|
||||
//obj.Scale = Util.ReadVector(reader, "Scale");
|
||||
obj.SetScale(Util.ReadVector(reader, "Scale"));
|
||||
}
|
||||
|
||||
private static void ProcessUpdateFlag(SceneObjectPart obj, XmlTextReader reader)
|
||||
|
@ -702,6 +712,55 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
|
|||
{
|
||||
obj.LastUpdateActorID = reader.ReadElementContentAsString("LastUpdateActorID", string.Empty);
|
||||
}
|
||||
|
||||
public static void ProcessBucketSyncInfo(SceneObjectPart obj, XmlTextReader reader)
|
||||
{
|
||||
obj.BucketSyncInfoList = new Dictionary<string, BucketSyncInfo>();
|
||||
|
||||
if (reader.IsEmptyElement)
|
||||
{
|
||||
reader.Read();
|
||||
return;
|
||||
}
|
||||
string elementName = "BucketSyncInfoList";
|
||||
reader.ReadStartElement(elementName, String.Empty);
|
||||
|
||||
while (reader.Name == "Bucket")
|
||||
{
|
||||
reader.ReadStartElement("Bucket", String.Empty); // Bucket
|
||||
string bucketName="";
|
||||
long timeStamp = 0;
|
||||
string actorID = "";
|
||||
while (reader.NodeType != XmlNodeType.EndElement)
|
||||
{
|
||||
|
||||
switch (reader.Name)
|
||||
{
|
||||
case "Name":
|
||||
bucketName = reader.ReadElementContentAsString("Name", String.Empty);
|
||||
break;
|
||||
case "TimeStamp":
|
||||
timeStamp = reader.ReadElementContentAsLong("TimeStamp", String.Empty);
|
||||
break;
|
||||
case "ActorID":
|
||||
actorID = reader.ReadElementContentAsString("ActorID", String.Empty);
|
||||
break;
|
||||
default:
|
||||
reader.ReadOuterXml();
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
reader.ReadEndElement();
|
||||
BucketSyncInfo bucketSyncInfo = new BucketSyncInfo(timeStamp, actorID, bucketName);
|
||||
obj.BucketSyncInfoList.Add(bucketName, bucketSyncInfo);
|
||||
}
|
||||
|
||||
if (reader.NodeType == XmlNodeType.EndElement)
|
||||
reader.ReadEndElement(); // BucketSyncInfoList
|
||||
}
|
||||
|
||||
//end of SYMMETRIC SYNC
|
||||
|
||||
#endregion
|
||||
|
@ -1188,11 +1247,36 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
|
|||
//SYMMETRIC SYNC
|
||||
writer.WriteElementString("LastUpdateTimeStamp", sop.LastUpdateTimeStamp.ToString());
|
||||
writer.WriteElementString("LastUpdateActorID", sop.LastUpdateActorID);
|
||||
WriteBucketSyncInfo(writer, sop.BucketSyncInfoList);
|
||||
//end of SYMMETRIC SYNC
|
||||
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
|
||||
//SYMMETRIC SYNC
|
||||
public static void WriteBucketSyncInfo(XmlTextWriter writer, Dictionary<string, BucketSyncInfo> bucketSyncInfoList)
|
||||
{
|
||||
if (bucketSyncInfoList!=null || bucketSyncInfoList.Count > 0) // otherwise skip this
|
||||
{
|
||||
|
||||
writer.WriteStartElement("BucketSyncInfoList");
|
||||
foreach (KeyValuePair<string, BucketSyncInfo> pair in bucketSyncInfoList)
|
||||
{
|
||||
BucketSyncInfo bucketSyncInfo = pair.Value;
|
||||
writer.WriteStartElement("Bucket");
|
||||
writer.WriteElementString("Name", bucketSyncInfo.BucketName);
|
||||
writer.WriteElementString("TimeStamp", bucketSyncInfo.LastUpdateTimeStamp.ToString());
|
||||
writer.WriteElementString("ActorID", bucketSyncInfo.LastUpdateActorID);
|
||||
writer.WriteEndElement(); // Bucket
|
||||
}
|
||||
|
||||
writer.WriteEndElement(); // BucketSyncInfo
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
//end of SYMMETRIC SYNC
|
||||
|
||||
static void WriteUUID(XmlTextWriter writer, string name, UUID id, Dictionary<string, object> options)
|
||||
{
|
||||
writer.WriteStartElement(name);
|
||||
|
|
Loading…
Reference in New Issue