Added code to include serialization/deserialization of BucketSyncInfoList in each SceneObjectPart.
parent
f36f1010b7
commit
ce4c8e4b6f
|
@ -179,12 +179,16 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
|||
get { return m_isSyncRelay; }
|
||||
}
|
||||
|
||||
private Dictionary<string, int> m_primPropertyBucketMap = new Dictionary<string, int>();
|
||||
public Dictionary<string, int> PrimPropertyBucketMap
|
||||
private Dictionary<string, string> m_primPropertyBucketMap = new Dictionary<string, string>();
|
||||
public Dictionary<string, string> PrimPropertyBucketMap
|
||||
{
|
||||
get { return m_primPropertyBucketMap; }
|
||||
}
|
||||
public List<string> PropertyBucketDescription = new List<string>();
|
||||
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;
|
||||
|
@ -201,21 +205,24 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
|||
//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.
|
||||
PropertyBucketDescription.Add("General");
|
||||
PropertyBucketDescription.Add("Physics");
|
||||
string generalBucketName = "General";
|
||||
string physicsBucketName = "Physics";
|
||||
m_propertyBucketDescription.Add(generalBucketName);
|
||||
m_propertyBucketDescription.Add(physicsBucketName);
|
||||
m_maxNumOfPropertyBuckets = 2;
|
||||
|
||||
int generalBucketID = 0;
|
||||
int physicsBucketID = 1;
|
||||
|
||||
foreach (string pName in SceneObjectPart.PropertyList)
|
||||
{
|
||||
switch (pName){
|
||||
|
@ -235,11 +242,11 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
|
|||
case "IsPhysical":
|
||||
case "Flying":
|
||||
case "Buoyancy":
|
||||
m_primPropertyBucketMap.Add(pName, physicsBucketID);
|
||||
m_primPropertyBucketMap.Add(pName, generalBucketName);
|
||||
break;
|
||||
default:
|
||||
//all other properties belong to the "General" bucket.
|
||||
m_primPropertyBucketMap.Add(pName, generalBucketID);
|
||||
m_primPropertyBucketMap.Add(pName, physicsBucketName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,7 +55,15 @@ namespace OpenSim.Region.Framework.Interfaces
|
|||
string ActorID { get; }
|
||||
DSGActorTypes DSGActorType { get; set; }
|
||||
bool IsSyncRelay { get; }
|
||||
Dictionary<string, int> PrimPropertyBucketMap { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The mapping of a property (identified by its name) to the index of a bucket.
|
||||
/// </summary>
|
||||
Dictionary<string, string> PrimPropertyBucketMap { get; }
|
||||
/// <summary>
|
||||
/// The text description of the properties in each bucket, e.g. "General", "Physics"
|
||||
/// </summary>
|
||||
List<string> PropertyBucketDescription { get; }
|
||||
|
||||
//Enqueue updates for scene-objects and scene-presences
|
||||
void QueueSceneObjectPartForUpdate(SceneObjectPart part);
|
||||
|
|
|
@ -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.RegionSyncClientModule != null)
|
||||
{
|
||||
foreach (SceneObjectPart part in Parts)
|
||||
{
|
||||
part.InitializeBucketSyncInfo();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Vector3 GroupScale()
|
||||
|
|
|
@ -116,6 +116,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
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
|
||||
{
|
||||
|
@ -127,10 +128,21 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
get { return m_lastUpdateActorID; }
|
||||
}
|
||||
|
||||
public BucketSyncInfo(long timeStamp, string actorID)
|
||||
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)
|
||||
|
@ -5096,11 +5108,12 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
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)
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -5223,6 +5236,8 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
|
||||
return partUpdateResult;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
private bool UpdateCollisionSound(UUID updatedCollisionSound)
|
||||
{
|
||||
|
@ -5276,34 +5291,170 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
|
||||
}
|
||||
|
||||
//The following three variables should be initialized when this SceneObjectPart is added into the local Scene.
|
||||
private List<BucketSyncInfo> m_bucketSyncInfo = null;
|
||||
private Dictionary<string, int> m_primPropertyBucketMap = null;
|
||||
private string m_localActorID = "";
|
||||
//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 = null;
|
||||
public Dictionary<string, BucketSyncInfo> BucketSyncInfoList
|
||||
{
|
||||
get { return m_bucketSyncInfoList; }
|
||||
set { m_bucketSyncInfoList = value; }
|
||||
}
|
||||
//TODO: serialization and deserialization processors to be added in SceneObjectSerializer
|
||||
|
||||
public void InitializeBucketSyncInfo(Dictionary<string, int> propertyBucketMap, string actorID)
|
||||
//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;
|
||||
int bucketNum = propertyBucketMap.Count;
|
||||
long timeStamp = DateTime.Now.Ticks;
|
||||
for (int i = 0; i < bucketNum; i++)
|
||||
m_bucketCount = propertyBucketMap.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)
|
||||
{
|
||||
BucketSyncInfo syncInfo = new BucketSyncInfo(timeStamp, m_localActorID);
|
||||
m_bucketSyncInfo.Add(syncInfo);
|
||||
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])
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//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;
|
||||
for (int i = 0; i < m_bucketCount; i++)
|
||||
{
|
||||
string bucketName = m_propertyBucketNames[i];
|
||||
BucketSyncInfo syncInfo = new BucketSyncInfo(timeStamp, m_localActorID, bucketName);
|
||||
m_bucketSyncInfoList.Add(bucketName, syncInfo);
|
||||
m_bucketUpdateLocks.Add(bucketName, new Object());
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateBucketSyncInfo(string propertyName)
|
||||
{
|
||||
if (m_bucketSyncInfo != null)
|
||||
if (m_bucketSyncInfoList != null)
|
||||
{
|
||||
int bucketIndex = m_primPropertyBucketMap[propertyName];
|
||||
//int bucketIndex = m_primPropertyBucketMap[propertyName];
|
||||
string bucketName = m_primPropertyBucketMap[propertyName];
|
||||
long timeStamp = DateTime.Now.Ticks;
|
||||
m_bucketSyncInfo[bucketIndex].UpdateSyncInfo(timeStamp, m_localActorID);
|
||||
m_bucketSyncInfoList[bucketName].UpdateSyncInfo(timeStamp, m_localActorID);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
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
|
||||
|
||||
}
|
||||
|
|
|
@ -330,8 +330,9 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
|
|||
m_SOPXmlProcessors.Add("ParticleSystem", ProcessParticleSystem);
|
||||
|
||||
//SYMMETRIC SYNC
|
||||
m_SOPXmlProcessors.Add("LastUpdateTimeStamp", ProcessUpdateTimeStamp);
|
||||
m_SOPXmlProcessors.Add("LastUpdateActorID", ProcessLastUpdateActorID);
|
||||
//m_SOPXmlProcessors.Add("LastUpdateTimeStamp", ProcessUpdateTimeStamp);
|
||||
//m_SOPXmlProcessors.Add("LastUpdateActorID", ProcessLastUpdateActorID);
|
||||
m_SOPXmlProcessors.Add("BucketSyncInfoList", ProcessBucketSyncInfo);
|
||||
//end of SYMMETRIC SYNC
|
||||
|
||||
#endregion
|
||||
|
@ -702,6 +703,55 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
|
|||
{
|
||||
obj.LastUpdateActorID = reader.ReadElementContentAsString("LastUpdateActorID", string.Empty);
|
||||
}
|
||||
|
||||
private 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
|
||||
|
@ -1186,13 +1236,36 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
|
|||
WriteBytes(writer, "ParticleSystem", sop.ParticleSystem);
|
||||
|
||||
//SYMMETRIC SYNC
|
||||
writer.WriteElementString("LastUpdateTimeStamp", sop.LastUpdateTimeStamp.ToString());
|
||||
writer.WriteElementString("LastUpdateActorID", sop.LastUpdateActorID);
|
||||
//writer.WriteElementString("LastUpdateTimeStamp", sop.LastUpdateTimeStamp.ToString());
|
||||
//writer.WriteElementString("LastUpdateActorID", sop.LastUpdateActorID);
|
||||
WriteBucketSyncInfo(writer, sop.BucketSyncInfoList);
|
||||
//end of SYMMETRIC SYNC
|
||||
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
|
||||
//SYMMETRIC SYNC
|
||||
static void WriteBucketSyncInfo(XmlTextWriter writer, Dictionary<string, BucketSyncInfo> bucketSyncInfoList)
|
||||
{
|
||||
if (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