Physics bucket packing and unpacking

dsg
Robert Adams 2011-02-16 17:11:16 -08:00
parent 21a1000da6
commit c9c94a5f23
16 changed files with 120 additions and 2481 deletions

View File

@ -1,530 +0,0 @@
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using OpenMetaverse;
using OpenMetaverse.Packets;
using OpenMetaverse.StructuredData;
using OpenSim.Framework;
using OpenSim.Services.Interfaces;
using OpenSim.Framework.Client;
using OpenSim.Region.Physics.Manager;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.Framework.Scenes.Serialization;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes.Types;
using log4net;
using Nini.Config;
namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
{
//The data structure that maintains the list of quarks a script engine subscribes to.
//It might be better to organize the quarks in a k-d tree structure, for easier
//partitioning of the quarks based on spatial information.
//But for now, we just assume the quarks each script engine operates on form a rectangle shape.
//So we just use xmin,ymin and xmax,ymax to identify the rectange; and use a List structure to
//store the quarks.
//Quark size is defined in QuarkInfo.SizeX and QuarkInfo.SizeY.
// The RegionSyncPhysEngine has a receive thread to process messages from the RegionSyncServer.
// It is the client side of the synchronization channel, and send to and receive updates from the
// Auth. Scene. The server side thread handling the sync channel is implemented in RegionSyncScriptAPI.cs.
//
// The current implementation is very similar to RegionSyncClient.
// TODO: eventually the same RegionSyncSceneAPI should handle all traffic from different actors, e.g.
// using a pub/sub model.
public class PhysEngineToSceneConnector
{
#region PhysEngineToSceneConnector members
// Set the addr and port of RegionSyncServer
private IPAddress m_addr;
private string m_addrString;
private Int32 m_port;
// A reference to the local scene
private Scene m_validLocalScene;
// The avatars added to this client manager for clients on other client managers
object m_syncRoot = new object();
// The logfile
private ILog m_log;
private string LogHeader = "[PHYSICS ENGINE TO SCENE CONNECTOR]";
// The listener and the thread which listens for connections from client managers
private Thread m_rcvLoop;
// The client connection to the RegionSyncServer
private TcpClient m_client = new TcpClient();
//KittyL: Comment out m_statsTimer for now, will figure out whether we need it for PhysEngine later
//private System.Timers.Timer m_statsTimer = new System.Timers.Timer(30000);
// The queue of incoming messages which need handling
//private Queue<string> m_inQ = new Queue<string>();
//KittyL: added to identify different actors
private ActorType m_actorType = ActorType.PhysicsEngine;
private bool m_debugWithViewer = false;
private long m_messagesSent = 0;
private long m_messagesReceived = 0;
private QuarkSubsriptionInfo m_subscribedQuarks;
private IConfig m_sysConfig;
//members for load balancing purpose
//private TcpClient m_loadMigrationSouceEnd = null;
private LoadMigrationEndPoint m_loadMigrationSouceEnd = null;
private Thread m_loadMigrationSrcRcvLoop;
private LoadMigrationListener m_loadMigrationListener = null;
//List of queued messages, when the space that the updated object is located is being migrated
private List<RegionSyncMessage> m_updateMsgQueue = new List<RegionSyncMessage>();
#endregion
// Constructor
public PhysEngineToSceneConnector(Scene validLocalScene, string addr, int port, bool debugWithViewer,
IConfig sysConfig)
{
m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
m_validLocalScene = validLocalScene;
m_addr = IPAddress.Parse(addr);
m_addrString = addr;
m_port = port;
m_debugWithViewer = debugWithViewer;
//m_statsTimer.Elapsed += new System.Timers.ElapsedEventHandler(StatsTimerElapsed);
m_sysConfig = sysConfig;
SceneToPhysEngineSyncServer.logEnabled = m_sysConfig.GetBoolean("LogEnabled", false);
SceneToPhysEngineSyncServer.logDir = m_sysConfig.GetString("LogDir", ".");
//assume we are connecting to the whole scene as one big quark
m_subscribedQuarks = new QuarkSubsriptionInfo(0, 0, (int)Constants.RegionSize, (int)Constants.RegionSize);
}
private List<string> GetQuarkStringList()
{
List<string> quarkList = new List<string>();
foreach (QuarkInfo quark in m_subscribedQuarks.QuarkList)
{
quarkList.Add(quark.QuarkStringRepresentation);
}
return quarkList;
}
// Start the RegionSyncPhysEngine client thread
public bool Start()
{
if (EstablishConnection())
{
StartStateSync();
return true;
}
else
{
return false;
}
}
private bool EstablishConnection()
{
if (m_client.Connected)
{
m_log.Warn(LogHeader + ": already connected");
return false;
}
try
{
m_client.Connect(m_addr, m_port);
}
catch (Exception e)
{
m_log.WarnFormat("{0} [Start] Could not connect to SceneToPhysEngineSyncServer at {1}:{2}", LogHeader, m_addr, m_port);
m_log.Warn(e.Message);
return false;
}
m_log.WarnFormat("{0} Connected to SceneToPhysEngineSyncServer at {1}:{2}", LogHeader, m_addr, m_port);
m_rcvLoop = new Thread(new ThreadStart(ReceiveLoop));
m_rcvLoop.Name = "PhysEngineToSceneConnector ReceiveLoop";
m_log.WarnFormat("{0} Starting {1} thread", LogHeader, m_rcvLoop.Name);
m_rcvLoop.Start();
return true;
}
private void StartStateSync()
{
RegionSyncMessage msg = new RegionSyncMessage(RegionSyncMessage.MsgType.ActorStatus, Convert.ToString((int)ActorStatus.Sync));
Send(msg);
// SendQuarkSubscription();
Thread.Sleep(100);
DoInitialSync();
}
private void SendQuarkSubscription()
{
List<string> quarkStringList = GetQuarkStringList();
string quarkString = RegionSyncUtil.QuarkStringListToString(quarkStringList);
m_log.Debug(LogHeader + ": subscribe to quarks: " + quarkString);
//Send(quarkString);
RegionSyncMessage msg = new RegionSyncMessage(RegionSyncMessage.MsgType.QuarkSubscription, quarkString);
Send(msg);
}
public void SetQuarkSubscription(QuarkSubsriptionInfo quarks)
{
m_subscribedQuarks = quarks;
}
public void RegisterIdle()
{
EstablishConnection();
RegionSyncMessage msg = new RegionSyncMessage(RegionSyncMessage.MsgType.ActorStatus, Convert.ToString((int)ActorStatus.Idle));
Send(msg);
}
private void DoInitialSync()
{
// m_validLocalScene.DeleteAllSceneObjects();
//m_log.Debug(LogHeader + ": send actor type " + m_actorType);
//Send(new RegionSyncMessage(RegionSyncMessage.MsgType.ActorType, Convert.ToString((int)m_actorType)));
//KittyL??? Do we need to send in RegionName?
//Send(new RegionSyncMessage(RegionSyncMessage.MsgType.RegionName, m_scene.RegionInfo.RegionName));
//m_log.WarnFormat("Sending region name: \"{0}\"", m_scene.RegionInfo.RegionName);
// Send(new RegionSyncMessage(RegionSyncMessage.MsgType.GetTerrain));
// Send(new RegionSyncMessage(RegionSyncMessage.MsgType.GetObjects));
// Register for events which will be forwarded to authoritative scene
// m_scene.EventManager.OnNewClient += EventManager_OnNewClient;
//m_scene.EventManager.OnClientClosed += new EventManager.ClientClosed(RemoveLocalClient);
}
// Disconnect from the RegionSyncServer and close client thread
public void Stop()
{
Send(new RegionSyncMessage(RegionSyncMessage.MsgType.ActorStop, "stop"));
// The remote scene will remove the SceneToPhysEngineConnector when we disconnect
m_rcvLoop.Abort();
ShutdownClient();
//stop the migration connections
//ShutdownClient(m_loadMigrationSouceEnd);
if (m_loadMigrationListener != null)
m_loadMigrationListener.Shutdown();
}
public void ReportStatus()
{
m_log.WarnFormat("{0} Synchronized to RegionSyncServer at {1}:{2}", LogHeader, m_addr, m_port);
m_log.WarnFormat("{0} Received={1}, Sent={2}", LogHeader, m_messagesReceived, m_messagesSent);
lock (m_syncRoot)
{
//TODO: should be reporting about the information of the objects/scripts
}
}
private void ShutdownClient()
{
m_log.WarnFormat("{0} Disconnected from RegionSyncServer. Shutting down.", LogHeader);
//TODO: remove the objects and scripts
//lock (m_syncRoot)
//{
//}
if (m_client != null)
{
// Close the connection
m_client.Client.Close();
m_client.Close();
}
SceneToPhysEngineSyncServer.PhysLogMessageClose();
}
// Listen for messages from a RegionSyncServer
// *** This is the main thread loop for each connected client
private void ReceiveLoop()
{
m_log.WarnFormat("{0} Thread running: {1}", LogHeader, m_rcvLoop.Name);
while (true && m_client.Connected)
{
RegionSyncMessage msg;
// Try to get the message from the network stream
try
{
msg = new RegionSyncMessage(m_client.GetStream());
//m_log.WarnFormat("{0} Received: {1}", LogHeader, msg.ToString());
}
// If there is a problem reading from the client, shut 'er down.
catch
{
ShutdownClient();
return;
}
// Try handling the message
try
{
//lock (m_syncRoot) -- KittyL: why do we need to lock here? We could lock inside HandleMessage if necessary, and lock on different objects for better performance
m_messagesReceived++;
HandleMessage(msg);
}
catch (Exception e)
{
m_log.WarnFormat("{0} Encountered an exception: {1} (MSGTYPE = {2})", LogHeader, e.Message, msg.ToString());
}
}
}
#region SEND
//DSG-TODO: for Scene based DSG, Send() also needs to figure out which Scene to send to, e.g. needs a switching function based on object position
// Send a message to a single connected RegionSyncServer
private void Send(string msg)
{
byte[] bmsg = System.Text.Encoding.ASCII.GetBytes(msg + System.Environment.NewLine);
Send(bmsg);
}
private void Send(RegionSyncMessage msg)
{
Send(msg.ToBytes());
//m_log.WarnFormat("{0} Sent {1}", LogHeader, msg.ToString());
}
private void Send(byte[] data)
{
if (m_client.Connected)
{
try
{
m_client.GetStream().Write(data, 0, data.Length);
m_messagesSent++;
}
// If there is a problem reading from the client, shut 'er down.
// *** Still need to alert the module that it's no longer connected!
catch
{
ShutdownClient();
}
}
}
#endregion SEND
//KittyL: Has to define SendCoarseLocations() here, since it's defined in IRegionSyncClientModule.
// But should not do much as being PhysEngine, not ClientManager
public void SendCoarseLocations()
{
}
// Handle an incoming message
// Dan-TODO: This should not be synchronous with the receive!
// Instead, handle messages from an incoming Queue so server doesn't block sending
//
// KittyL: This is the function that PhysEngine and ClientManager have the most different implementations
private void HandleMessage(RegionSyncMessage msg)
{
//TO FINISH:
SceneToPhysEngineSyncServer.PhysLogMessage(false, msg);
switch (msg.Type)
{
case RegionSyncMessage.MsgType.RegionName:
{
return;
}
case RegionSyncMessage.MsgType.PhysUpdateAttributes:
{
HandlePhysUpdateAttributes(msg);
return;
}
default:
{
RegionSyncMessage.HandleError(LogHeader, msg, String.Format("{0} Unsupported message type: {1}", LogHeader, ((int)msg.Type).ToString()));
return;
}
}
}
/// <summary>
/// The physics engine has some updates to the attributes. Unpack the parameters, find the
/// correct PhysicsActor and plug in the new values;
/// </summary>
/// <param name="msg"></param>
private void HandlePhysUpdateAttributes(RegionSyncMessage msg)
{
// TODO:
OSDMap data = RegionSyncUtil.DeserializeMessage(msg, LogHeader);
try
{
UUID uuid = data["uuid"].AsUUID();
string actorID = data["actorID"].AsString();
// m_log.DebugFormat("{0}: HandlPhysUpdateAttributes for {1}", LogHeader, uuid);
PhysicsActor pa = FindPhysicsActor(uuid);
if (pa != null)
{
// pa.Size = data["size"].AsVector3();
pa.Position = data["position"].AsVector3();
pa.Force = data["force"].AsVector3();
pa.Velocity = data["velocity"].AsVector3();
pa.RotationalVelocity = data["rotationalVelocity"].AsVector3();
pa.Acceleration = data["acceleration"].AsVector3();
pa.Torque = data["torque"].AsVector3();
pa.Orientation = data["orientation"].AsQuaternion();
pa.IsPhysical = data["isPhysical"].AsBoolean(); // receive??
pa.Flying = data["flying"].AsBoolean(); // receive??
pa.Kinematic = data["kinematic"].AsBoolean(); // receive??
pa.Buoyancy = (float)(data["buoyancy"].AsReal());
SceneObjectPart sop = m_validLocalScene.GetSceneObjectPart(uuid);
if (sop != null)
{
pa.Shape = sop.Shape;
}
pa.ChangingActorID = actorID;
m_validLocalScene.PhysicsScene.AddPhysicsActorTaint(pa);
}
else
{
m_log.WarnFormat("{0}: attribute update for unknown uuid {1}", LogHeader, uuid);
return;
}
}
catch (Exception e)
{
m_log.WarnFormat("{0}: EXCEPTION processing UpdateAttributes: {1}", LogHeader, e);
return;
}
return;
}
// Find the physics actor whether it is an object or a scene presence
private PhysicsActor FindPhysicsActor(UUID uuid)
{
SceneObjectPart sop = m_validLocalScene.GetSceneObjectPart(uuid);
if (sop != null)
{
return sop.PhysActor;
}
ScenePresence sp = m_validLocalScene.GetScenePresence(uuid);
if (sp != null)
{
return sp.PhysicsActor;
}
return null;
}
public void SendPhysUpdateAttributes(PhysicsActor pa)
{
// m_log.DebugFormat("{0}: SendPhysUpdateAttributes for {1}", LogHeader, pa.UUID);
OSDMap data = new OSDMap(17);
data["time"] = OSD.FromString(DateTime.Now.ToString("yyyyMMddHHmmssfff"));
data["localID"] = OSD.FromUInteger(pa.LocalID);
data["uuid"] = OSD.FromUUID(pa.UUID);
data["actorID"] = OSD.FromString(RegionSyncServerModule.ActorID);
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["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["buoyancy"] = OSD.FromReal(pa.Buoyancy);
data["isColliding"] = OSD.FromBoolean(pa.IsColliding);
data["isCollidingGround"] = OSD.FromBoolean(pa.CollidingGround);
RegionSyncMessage rsm = new RegionSyncMessage(RegionSyncMessage.MsgType.PhysUpdateAttributes,
OSDParser.SerializeJsonString(data));
Send(rsm);
return;
}
#region Utility functions
private OSDMap GetOSDMap(string strdata)
{
OSDMap args = null;
OSD buffer = OSDParser.DeserializeJson(strdata);
if (buffer.Type == OSDType.Map)
{
args = (OSDMap)buffer;
return args;
}
return null;
}
HashSet<string> exceptions = new HashSet<string>();
private OSDMap DeserializeMessage(RegionSyncMessage msg)
{
OSDMap data = null;
try
{
data = OSDParser.DeserializeJson(Encoding.ASCII.GetString(msg.Data, 0, msg.Length)) as OSDMap;
}
catch (Exception e)
{
lock (exceptions)
// If this is a new message, then print the underlying data that caused it
if (!exceptions.Contains(e.Message))
m_log.Error(LogHeader + " " + Encoding.ASCII.GetString(msg.Data, 0, msg.Length));
data = null;
}
return data;
}
public string GetServerAddressAndPort()
{
return m_addr.ToString() + ":" + m_port.ToString();
}
#endregion Utility functions
#region Handlers for Scene events
private void HandleAddOrUpdateObjectInLocalScene(RegionSyncMessage msg)
{
// TODO: modify for physics
OSDMap data = DeserializeMessage(msg);
/*
if (data["locX"] == null || data["locY"] == null || data["sogXml"] == null)
{
m_log.Warn(LogHeader + ": parameters missing in NewObject/UpdatedObject message, need to have locX, locY, sogXml");
return;
}
* */
uint locX = data["locX"].AsUInteger();
uint locY = data["locY"].AsUInteger();
string sogxml = data["sogXml"].AsString();
SceneObjectGroup sog = SceneObjectSerializer.FromXml2Format(sogxml);
}
#endregion Handlers for events/updates from Scene
}
}

View File

@ -1,472 +0,0 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* 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.
* * Neither the name of the OpenSim Project nor the
* names of its contributors may 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.Reflection;
using Nini.Config;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Framework.Client;
using OpenSim.Region.CoreModules.Framework.InterfaceCommander;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.Physics.Manager;
using OpenSim.Services.Interfaces;
using log4net;
using System.Net;
using System.Net.Sockets;
namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
{
//The connector that connects the local Scene (cache) and remote authoratative Scene
public class PhysEngineToSceneConnectorModule : IRegionModule, IPhysEngineToSceneConnectorModule, ICommandableModule
{
#region PhysEngineToSceneConnectorModule members and functions
private static int m_activeActors = 0;
private bool m_active = false;
private string m_serveraddr;
private int m_serverport;
private Scene m_scene;
private static List<Scene> m_allScenes = new List<Scene>();
private ILog m_log;
private Object m_client_lock = new Object();
//private PhysEngineToSceneConnector m_scriptEngineToSceneConnector = null;
private IConfig m_syncConfig = null;
public IConfig SyncConfig { get { return m_syncConfig; } }
private bool m_debugWithViewer = false;
public bool DebugWithViewer { get { return m_debugWithViewer; } }
private string m_regionSyncMode = "";
//Variables relavant for multi-scene subscription.
private Dictionary<string, PhysEngineToSceneConnector> m_PEToSceneConnectors = new Dictionary<string, PhysEngineToSceneConnector>(); //connector for each auth. scene
private string LogHeader = "[PhysEngineToSceneConnectorModule]";
private PhysEngineToSceneConnector m_idlePEToSceneConnector = null;
private PhysEngineToSceneConnector m_physEngineToSceneConnector = null;
//quark information
//private int QuarkInfo.SizeX;
//private int QuarkInfo.SizeY;
//private string m_quarkListString;
private string m_subscriptionSpaceString;
#endregion PhysEngineToSceneConnectorModule members and functions
#region IRegionModule Members
public void Initialise(Scene scene, IConfigSource config)
{
m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
m_active = false; //set to false unless this is the valid local scene
//Read in configuration
IConfig syncConfig = config.Configs["RegionSyncModule"];
if (syncConfig != null
&& syncConfig.GetBoolean("Enabled", false)
// && syncConfig.GetString("Mode", "").ToLower() == "client"
&& syncConfig.GetBoolean("PhysEngineClient", false)
)
{
//scene.RegionSyncEnabled = true;
}
else
{
//scene.RegionSyncEnabled = false;
m_log.Warn(LogHeader + ": Not in physics engine client mode. Shutting down.");
return;
}
m_active = true;
m_activeActors++;
m_log.Debug(LogHeader + " Init PEToSceneConnectorModule, for local scene " + scene.RegionInfo.RegionName);
m_scene = scene;
m_scene.RegisterModuleInterface<IPhysEngineToSceneConnectorModule>(this);
m_syncConfig = syncConfig;
m_debugWithViewer = syncConfig.GetBoolean("PhysEngineDebugWithViewer", false);
//read in the quark size information
//QuarkInfo.SizeX = syncConfig.GetInt("QuarkSizeX", (int)Constants.RegionSize);
//QuarkInfo.SizeY = syncConfig.GetInt("QuarkSizeY", (int)Constants.RegionSize);
QuarkInfo.SizeX = syncConfig.GetInt("QuarkSizeX", (int)Constants.RegionSize);
QuarkInfo.SizeY = syncConfig.GetInt("QuarkSizeY", (int)Constants.RegionSize);
//m_quarkListString = syncConfig.GetString("InitQuarkSet", ""); //if not specified, dost not subscribe to any quark
//if (m_quarkListString.Equals("all"))
//{
// m_quarkListString = RegionSyncUtil.QuarkStringListToString(RegionSyncUtil.GetAllQuarkStringInScene(QuarkInfo.SizeX, QuarkInfo.SizeY));
//}
m_subscriptionSpaceString = syncConfig.GetString("InitSubscriptionSpace", "0_0,256_256");
// Setup the command line interface
m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole;
InstallInterfaces();
m_log.Warn(LogHeader + " Initialised");
// collect all the scenes for later routing
if (!m_allScenes.Contains(scene))
{
m_allScenes.Add(scene);
}
}
public void PostInitialise()
{
if (!m_active)
return;
Start(); // fake a 'phys start' to get things going
//m_log.Warn(LogHeader + " Post-Initialised");
}
public void Close()
{
if (m_active)
{
}
m_scene = null;
m_active = false;
m_activeActors--;
}
public string Name
{
get { return "RegionSyncPhysEngineModule"; }
}
public bool IsSharedModule
{
get { return false; }
}
#endregion
#region ICommandableModule Members
private readonly Commander m_commander = new Commander("phys");
public ICommander CommandInterface
{
get { return m_commander; }
}
#endregion
#region IPhysEngineToSceneConnectorModule members
public bool Active
{
get { return m_active; }
}
public bool Synced
{
get
{
lock(m_client_lock)
{
return (m_PEToSceneConnectors.Count > 0);
}
}
}
bool IPhysEngineToSceneConnectorModule.IsPhysEngineActor()
{
return PhysEngineToSceneConnectorModule.IsPhysEngineActorS;
}
bool IPhysEngineToSceneConnectorModule.IsPhysEngineScene()
{
return PhysEngineToSceneConnectorModule.IsPhysEngineSceneS;
}
bool IPhysEngineToSceneConnectorModule.IsActivePhysEngineScene()
{
return PhysEngineToSceneConnectorModule.IsActivePhysEngineSceneS;
}
public static bool IsPhysEngineSceneS
{
get { return SceneToPhysEngineSyncServer.IsPhysEngineScene2S(); }
}
public static bool IsActivePhysEngineSceneS
{
get { return SceneToPhysEngineSyncServer.IsActivePhysEngineScene2S(); }
}
public static bool IsPhysEngineActorS
{
get { return (m_activeActors != 0); }
}
/// <summary>
/// The scene is unknown by ODE so we have to look through the scenes to
/// find the one with this PhysicsActor so we can send the update.
/// </summary>
/// <param name="pa"></param>
public static void RouteUpdate(PhysicsActor pa)
{
SceneObjectPart sop;
ScenePresence sp;
Scene s = null;
foreach (Scene ss in m_allScenes)
{
try
{
sop = ss.GetSceneObjectPart(pa.UUID);
}
catch
{
sop = null;
}
if (sop != null)
{
s = ss;
break;
}
try
{
sp = ss.GetScenePresence(pa.UUID);
}
catch
{
sp = null;
}
if (sp != null)
{
s = ss;
break;
}
}
if (s != null)
{
if (s.PhysEngineToSceneConnectorModule != null)
{
s.PhysEngineToSceneConnectorModule.SendUpdate(pa);
}
else
{
Console.WriteLine("RouteUpdate: PhysEngineToSceneConnectorModule is null");
}
}
else
{
Console.WriteLine("RouteUpdate: no SOP found for {0}", pa.UUID);
}
return;
}
#endregion
#region Event Handlers
#endregion
private void DebugSceneStats()
{
return;
/*
List<ScenePresence> avatars = m_scene.GetAvatars();
List<EntityBase> entities = m_scene.GetEntities();
m_log.WarnFormat("{0} There are {1} avatars and {2} entities in the scene", LogHeader, avatars.Count, entities.Count);
*/
}
public void SendUpdate(PhysicsActor pa)
{
if (this.m_physEngineToSceneConnector != null)
{
this.m_physEngineToSceneConnector.SendPhysUpdateAttributes(pa);
}
}
#region Console Command Interface
//IMPORTANT: these functions should only be actived for the PhysEngineToSceneConnectorModule that is associated with the valid local scene
private void InstallInterfaces()
{
Command cmdSyncStart = new Command("start", CommandIntentions.COMMAND_HAZARDOUS, SyncStart, "Begins synchronization with RegionSyncServer.");
//cmdSyncStart.AddArgument("server_port", "The port of the server to synchronize with", "Integer");
Command cmdSyncStop = new Command("stop", CommandIntentions.COMMAND_HAZARDOUS, SyncStop, "Stops synchronization with RegionSyncServer.");
//cmdSyncStop.AddArgument("server_address", "The IP address of the server to synchronize with", "String");
//cmdSyncStop.AddArgument("server_port", "The port of the server to synchronize with", "Integer");
Command cmdSyncStatus = new Command("status", CommandIntentions.COMMAND_HAZARDOUS, SyncStatus, "Displays synchronization status.");
//The following two commands are more for easier debugging purpose
Command cmdSyncSetQuarks = new Command("quarkSpace", CommandIntentions.COMMAND_HAZARDOUS, SetQuarkList, "Set the set of quarks to subscribe to. For debugging purpose. Should be issued before \"sync start\"");
cmdSyncSetQuarks.AddArgument("quarkSpace", "The (rectangle) space of quarks to subscribe, represented by x0_y0,x1_y1, the left-bottom and top-right corners of the rectangel space", "String");
Command cmdSyncSetQuarkSize = new Command("quarksize", CommandIntentions.COMMAND_HAZARDOUS, SetQuarkSize, "Set the size of each quark. For debugging purpose. Should be issued before \"sync quarks\"");
cmdSyncSetQuarkSize.AddArgument("quarksizeX", "The size on x axis of each quark", "Integer");
cmdSyncSetQuarkSize.AddArgument("quarksizeY", "The size on y axis of each quark", "Integer");
m_commander.RegisterCommand("start", cmdSyncStart);
m_commander.RegisterCommand("stop", cmdSyncStop);
m_commander.RegisterCommand("status", cmdSyncStatus);
m_commander.RegisterCommand("quarkSpace", cmdSyncSetQuarks);
lock (m_scene)
{
// Add this to our scene so scripts can call these functions
m_scene.RegisterModuleCommander(m_commander);
}
}
/// <summary>
/// Processes commandline input. Do not call directly.
/// </summary>
/// <param name="args">Commandline arguments</param>
private void EventManager_OnPluginConsole(string[] args)
{
if (args[0] == "phys")
{
if (args.Length == 1)
{
m_commander.ProcessConsoleCommand("help", new string[0]);
return;
}
string[] tmpArgs = new string[args.Length - 2];
int i;
for (i = 2; i < args.Length; i++)
tmpArgs[i - 2] = args[i];
m_commander.ProcessConsoleCommand(args[1], tmpArgs);
}
}
private void SyncStart(Object[] args)
{
Start();
}
private void Start()
{
m_serveraddr = m_scene.RegionInfo.PhysicsSyncServerAddress;
m_serverport = m_scene.RegionInfo.PhysicsSyncServerPort;
lock (m_client_lock)
{
//m_log.Warn(LogHeader + " Starting synchronization");
m_log.Warn(LogHeader + ": Starting RegionSyncPhysEngine");
//Only one remote scene to connect to. Subscribe to whatever specified in the config file.
//List<string> quarkStringList = RegionSyncUtil.QuarkStringToStringList(m_quarkListString);
//InitPhysEngineToSceneConnector(quarkStringList);
InitPhysEngineToSceneConnector(m_subscriptionSpaceString);
}
}
private void SetQuarkList(Object[] args)
{
m_subscriptionSpaceString = (string)args[0];
InitPhysEngineToSceneConnector(m_subscriptionSpaceString);
}
private void SetQuarkSize(Object[] args)
{
QuarkInfo.SizeX = (int)args[0];
QuarkInfo.SizeY = (int)args[1];
}
private void InitPhysEngineToSceneConnector(string space)
{
m_physEngineToSceneConnector = new PhysEngineToSceneConnector(m_scene,
m_serveraddr, m_serverport, m_debugWithViewer, /* space,*/ m_syncConfig);
if (m_physEngineToSceneConnector.Start())
{
m_PEToSceneConnectors.Add(m_scene.RegionInfo.RegionName, m_physEngineToSceneConnector);
}
}
private void SyncStop(Object[] args)
{
lock (m_client_lock)
{
//if (m_scriptEngineToSceneConnector == null)
if(m_PEToSceneConnectors.Count==0 && m_idlePEToSceneConnector==null)
{
m_log.Warn(LogHeader + " Already stopped");
return;
}
if (m_PEToSceneConnectors.Count > 0)
{
foreach (KeyValuePair<string, PhysEngineToSceneConnector> valPair in m_PEToSceneConnectors)
{
PhysEngineToSceneConnector connector = valPair.Value;
if (connector == null)
{
continue;
}
connector.Stop();
}
m_PEToSceneConnectors.Clear();
}
else if (m_idlePEToSceneConnector != null)
{
m_idlePEToSceneConnector.Stop();
m_idlePEToSceneConnector = null;
}
//m_scriptEngineToSceneConnector.Stop();
//m_scriptEngineToSceneConnector = null;
m_log.Warn(LogHeader+": Stopping synchronization");
}
//save script state and stop script instances
// TODO: Load balancing. next line commented out to compile
// m_scene.EventManager.TriggerPhysEngineSyncStop();
//remove all objects
m_scene.DeleteAllSceneObjects();
}
private void SyncStatus(Object[] args)
{
lock (m_client_lock)
{
if (m_PEToSceneConnectors.Count == 0)
{
m_log.Warn(LogHeader + " Not currently synchronized");
return;
}
foreach (KeyValuePair<string, PhysEngineToSceneConnector> pair in m_PEToSceneConnectors)
{
PhysEngineToSceneConnector sceneConnector = pair.Value;
sceneConnector.ReportStatus();
}
}
}
#endregion
}
}

View File

@ -601,7 +601,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags) public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags)
{ {
m_log.Debug("[REGION SYNC AVATAR] SendPrimUpdate"); // m_log.Debug("[REGION SYNC AVATAR] SendPrimUpdate");
} }
public virtual void AttachObject(uint localID, Quaternion rotation, byte attachPoint, UUID ownerID) public virtual void AttachObject(uint localID, Quaternion rotation, byte attachPoint, UUID ownerID)

View File

@ -190,6 +190,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
m_sceneToSESyncServer.Start(); m_sceneToSESyncServer.Start();
} }
/*
m_peSyncServeraddr = m_scene.RegionInfo.PhysicsSyncServerAddress; m_peSyncServeraddr = m_scene.RegionInfo.PhysicsSyncServerAddress;
m_peSyncServerport = m_scene.RegionInfo.PhysicsSyncServerPort; m_peSyncServerport = m_scene.RegionInfo.PhysicsSyncServerPort;
if (!m_peSyncServeraddr.Equals(IPAddrUnknown) && m_peSyncServerport != PortUnknown) if (!m_peSyncServeraddr.Equals(IPAddrUnknown) && m_peSyncServerport != PortUnknown)
@ -199,6 +200,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
m_sceneToPESyncServer = new SceneToPhysEngineSyncServer(m_scene, m_peSyncServeraddr, m_peSyncServerport); m_sceneToPESyncServer = new SceneToPhysEngineSyncServer(m_scene, m_peSyncServeraddr, m_peSyncServerport);
m_sceneToPESyncServer.Start(); m_sceneToPESyncServer.Start();
} }
*/
//m_log.Warn("[REGION SYNC SERVER MODULE] Post-Initialised"); //m_log.Warn("[REGION SYNC SERVER MODULE] Post-Initialised");
} }
@ -520,11 +522,6 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
private int m_seSyncServerport; private int m_seSyncServerport;
private SceneToScriptEngineSyncServer m_sceneToSESyncServer = null; private SceneToScriptEngineSyncServer m_sceneToSESyncServer = null;
//Sync-server for physics engine
private string m_peSyncServeraddr;
private int m_peSyncServerport;
private SceneToPhysEngineSyncServer m_sceneToPESyncServer = null;
//a boolean variable to indicate in symmetric sync is configured //a boolean variable to indicate in symmetric sync is configured
//private bool m_symsync = false; //private bool m_symsync = false;

View File

@ -1,559 +0,0 @@
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Collections.Generic;
using System.Threading;
using OpenMetaverse;
using OpenMetaverse.Packets;
using OpenMetaverse.StructuredData;
using OpenSim.Framework;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.Framework.Scenes.Serialization;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Physics.Manager;
using log4net;
namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
{
//KittyL: NOTE -- We need to define an interface for all actors to connect into the Scene,
// e.g. IActorConnector, that runs on the Scene side, processes messages from actors,
// and apply Scene/Object operations.
// The SceneToPhysEngineConnector acts as a thread on the RegionSyncServer to handle incoming
// messages from PhysEngineToSceneConnectors that run on Physics Engines. It connects the
// authoratative Scene with remote script engines.
public class SceneToPhysEngineConnector
{
#region SceneToPhysEngineConnector members
object stats = new object();
private DateTime lastStatTime;
private long msgsIn;
private long msgsOut;
private long bytesIn;
private long bytesOut;
private long pollBlocks;
private int lastTotalCount;
private int lastLocalCount;
private int lastRemoteCount;
private int msgCount = 0;
// The TcpClient this view uses to communicate with its RegionSyncClient
private TcpClient m_tcpclient;
// Set the addr and port for TcpListener
private IPAddress m_addr;
private Int32 m_port;
private int m_connection_number;
private Scene m_scene;
object m_syncRoot = new object();
Dictionary<UUID, RegionSyncAvatar> m_syncedAvatars = new Dictionary<UUID, RegionSyncAvatar>();
// A queue for incoming and outgoing traffic
private OpenMetaverse.BlockingQueue<RegionSyncMessage> inbox = new OpenMetaverse.BlockingQueue<RegionSyncMessage>();
private OpenMetaverse.BlockingQueue<RegionSyncMessage> outbox = new OpenMetaverse.BlockingQueue<RegionSyncMessage>();
private ILog m_log;
private Thread m_receive_loop;
private string m_regionName;
private SceneToPhysEngineSyncServer m_syncServer = null;
// A string of the format [REGION SYNC SCRIPT API (regionname)] for use in log headers
private string LogHeader
{
get
{
if (m_regionName == null)
return String.Format("[SceneToPhysEngineConnector #{0}]", m_connection_number);
return String.Format("[SceneToPhysEngineConnector #{0} ({1:10})]", m_connection_number, m_regionName);
}
}
// A string of the format "RegionSyncClientView #X" for use in describing the object itself
public string Description
{
get
{
if (m_regionName == null)
return String.Format("RegionSyncPhysAPI #{0}", m_connection_number);
return String.Format("RegionSyncPhysAPI #{0} ({1:10})", m_connection_number, m_regionName);
}
}
public int ConnectionNum
{
get { return m_connection_number; }
}
public string GetStats()
{
string ret;
//lock (m_syncRoot)
// syncedAvCount = m_syncedAvatars.Count;
lock (stats)
{
double secondsSinceLastStats = DateTime.Now.Subtract(lastStatTime).TotalSeconds;
lastStatTime = DateTime.Now;
// ret = String.Format("[{0,4}/{1,4}], [{2,4}/{3,4}], [{4,4}/{5,4}], [{6,4} ({7,4})], [{8,8} ({9,8:00.00})], [{10,4} ({11,4})], [{12,8} ({13,8:00.00})], [{14,8} ({15,4}]",
ret = String.Format("[{0,4}/{1,4}], [{2,6}/{3,6}], [{4,4}/{5,4}], [{6,6} ({7,6})], [{8,4} ({9,4})]",
//lastTotalCount, totalAvCount, // TOTAL AVATARS
//lastLocalCount, syncedAvCount, // LOCAL TO THIS CLIENT VIEW
//lastRemoteCount, totalAvCount - syncedAvCount, // REMOTE (SHOULD = TOTAL - LOCAL)
msgsIn, (int)(msgsIn / secondsSinceLastStats),
bytesIn, 8 * (bytesIn / secondsSinceLastStats / 1000000), // IN
msgsOut, (int)(msgsOut / secondsSinceLastStats),
bytesOut, 8 * (bytesOut / secondsSinceLastStats / 1000000), // OUT
pollBlocks, (int)(pollBlocks / secondsSinceLastStats)); // NUMBER OF TIMES WE BLOCKED WRITING TO SOCKET
msgsIn = msgsOut = bytesIn = bytesOut = pollBlocks = 0;
}
return ret;
}
// Check if the client is connected
public bool Connected
{ get { return m_tcpclient.Connected; } }
//private int QuarkInfo.SizeX;
//private int QuarkInfo.SizeY;
//private List<QuarkInfo> m_quarkSubscriptions;
Dictionary<string, QuarkInfo> m_quarkSubscriptions;
public Dictionary<string, QuarkInfo> QuarkSubscriptionList
{
get { return m_quarkSubscriptions; }
}
#endregion
// Constructor
public SceneToPhysEngineConnector(int num, Scene scene, TcpClient client, SceneToPhysEngineSyncServer syncServer)
{
m_connection_number = num;
m_scene = scene;
m_tcpclient = client;
m_addr = ((IPEndPoint)client.Client.RemoteEndPoint).Address;
m_port = ((IPEndPoint)client.Client.RemoteEndPoint).Port;
m_syncServer = syncServer;
//QuarkInfo.SizeX = quarkSizeX;
//QuarkInfo.SizeY = quarkSizeY;
m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
//m_log.WarnFormat("{0} Constructed", LogHeader);
//Register for events from Scene.EventManager
//m_scene.EventManager.OnRezScript += SEConnectorOnRezScript;
//m_scene.EventManager.OnScriptReset += SEConnectorOnScriptReset;
//m_scene.EventManager.OnUpdateScript += SEConnectorOnUpdateScript;
// Create a thread for the receive loop
m_receive_loop = new Thread(new ThreadStart(delegate() { ReceiveLoop(); }));
m_receive_loop.Name = Description;
//m_log.WarnFormat("{0} Started thread: {1}", LogHeader, m_receive_loop.Name);
m_receive_loop.Start();
//tell the remote script engine about the locX, locY of this authoritative scene
// SendSceneLoc();
m_log.DebugFormat("{0}: SceneToPhysEngineConnector initialized", LogHeader);
}
// Stop the listening thread, disconnecting the RegionSyncPhysEngine
public void Shutdown()
{
m_syncServer.RemoveSyncedPhysEngine(this);
// m_scene.EventManager.OnChatFromClient -= EventManager_OnChatFromClient;
// Abort ReceiveLoop Thread, close Socket and TcpClient
m_receive_loop.Abort();
m_tcpclient.Client.Close();
m_tcpclient.Close();
//m_scene.EventManager.OnRezScript -= SEConnectorOnRezScript;
//m_scene.EventManager.OnScriptReset -= SEConnectorOnScriptReset;
//m_scene.EventManager.OnUpdateScript -= SEConnectorOnUpdateScript;
}
#region Send/Receive messages to/from the remote Physics Engine
// Listen for messages from a RegionSyncClient
// *** This is the main thread loop for each connected client
private void ReceiveLoop()
{
//m_scene.EventManager.OnChatFromClient += new EventManager.ChatFromClientEvent(EventManager_OnChatFromClient);
// Reset stats and time
lastStatTime = DateTime.Now;
msgsIn = msgsOut = bytesIn = bytesOut = 0;
try
{
while (true)
{
RegionSyncMessage msg = GetMessage();
lock (stats)
{
msgsIn++;
bytesIn += msg.Length;
}
lock (m_syncRoot)
HandleMessage(msg);
}
}
catch (Exception e)
{
m_log.WarnFormat("{0}: has disconnected: {1}", LogHeader, e.Message);
}
Shutdown();
}
// Get a message from the RegionSyncClient
private RegionSyncMessage GetMessage()
{
// Get a RegionSyncMessager from the incoming stream
RegionSyncMessage msg = new RegionSyncMessage(m_tcpclient.GetStream());
//m_log.WarnFormat("{0} Received {1}", LogHeader, msg.ToString());
return msg;
}
// Handle an incoming message
// *** Perhaps this should not be synchronous with the receive
// We could handle messages from an incoming Queue
private void HandleMessage(RegionSyncMessage msg)
{
SceneToPhysEngineSyncServer.PhysLogMessage(true, msg);
msgCount++;
//string handlerMessage = "";
switch (msg.Type)
{
case RegionSyncMessage.MsgType.ActorStop:
{
Shutdown();
}
return;
/*
case RegionSyncMessage.MsgType.LoadBalanceRequest:
{
m_syncServer.HandleLoadBalanceRequest(this);
return;
}
case RegionSyncMessage.MsgType.ActorStatus:
{
string status = Encoding.ASCII.GetString(msg.Data, 0, msg.Length);
ActorStatus actorStatus = (ActorStatus)Convert.ToInt32(status);
if (actorStatus == ActorStatus.Sync)
{
m_log.Debug(LogHeader + ": received ActorStatus " + actorStatus.ToString());
m_syncServer.AddSyncedPhysEngine(this);
}
else
{
m_log.Warn(LogHeader + ": not supposed to received RegionSyncMessage.MsgType.ActorStatus==" + status.ToString());
}
return;
}
*/
case RegionSyncMessage.MsgType.PhysTerseUpdate:
{
HandlePhysTerseUpdate(msg);
return;
}
case RegionSyncMessage.MsgType.PhysOutOfBounds:
{
HandlePhysOutOfBounds(msg);
return;
}
case RegionSyncMessage.MsgType.PhysCollisionUpdate:
{
HandlePhysCollisionUpdate(msg);
return;
}
case RegionSyncMessage.MsgType.PhysUpdateAttributes:
{
HandlePhysUpdateAttributes(msg);
return;
}
default:
{
m_log.WarnFormat("{0} Unable to handle unsupported message type", LogHeader);
return;
}
}
}
private void HandlePhysTerseUpdate(RegionSyncMessage msg)
{
OSDMap data = RegionSyncUtil.DeserializeMessage(msg, LogHeader);
try
{
UUID uuid = data["uuid"].AsUUID();
// m_log.DebugFormat("{0}: received PhysUpdateAttributes for {1}", LogHeader, uuid);
PhysicsActor pa = FindPhysicsActor(uuid);
if (pa != null)
{
pa.RequestPhysicsterseUpdate();
}
else
{
m_log.WarnFormat("{0}: terse update for unknown uuid {1}", LogHeader, uuid);
return;
}
}
catch (Exception e)
{
m_log.WarnFormat("{0}: EXCEPTION processing PhysTerseUpdate: {1}", LogHeader, e);
return;
}
return;
}
private void HandlePhysOutOfBounds(RegionSyncMessage msg)
{
// TODO:
return;
}
private void HandlePhysCollisionUpdate(RegionSyncMessage msg)
{
// TODO:
return;
}
/// <summary>
/// The physics engine has some updates to the attributes. Unpack the parameters, find the
/// correct PhysicsActor and plug in the new values;
/// </summary>
/// <param name="msg"></param>
private void HandlePhysUpdateAttributes(RegionSyncMessage msg)
{
OSDMap data = RegionSyncUtil.DeserializeMessage(msg, LogHeader);
try
{
UUID uuid = data["uuid"].AsUUID();
string actorID = data["actorID"].AsString();
// m_log.DebugFormat("{0}: received PhysUpdateAttributes for {1}", LogHeader, uuid);
PhysicsActor pa = FindPhysicsActor(uuid);
if (pa != null)
{
pa.Size = data["size"].AsVector3();
pa.Position = data["position"].AsVector3();
pa.Force = data["force"].AsVector3();
pa.Velocity = data["velocity"].AsVector3();
pa.RotationalVelocity = data["rotationalVelocity"].AsVector3();
pa.Acceleration = data["acceleration"].AsVector3();
pa.Torque = data["torque"].AsVector3();
pa.Orientation = data["orientation"].AsQuaternion();
pa.IsPhysical = data["isPhysical"].AsBoolean(); // receive??
pa.Flying = data["flying"].AsBoolean(); // receive??
pa.Kinematic = data["kinematic"].AsBoolean(); // receive??
pa.Buoyancy = (float)(data["buoyancy"].AsReal());
pa.CollidingGround = data["isCollidingGround"].AsBoolean();
pa.IsColliding = data["isCollidingGround"].AsBoolean();
pa.ChangingActorID = actorID;
pa.RequestPhysicsterseUpdate(); // tell the system the values have changed
}
else
{
m_log.WarnFormat("{0}: attribute update for unknown uuid {1}", LogHeader, uuid);
return;
}
}
catch (Exception e)
{
m_log.WarnFormat("{0}: EXCEPTION processing UpdateAttributes: {1}", LogHeader, e);
return;
}
return;
}
// Find the physics actor whether it is an object or a scene presence
private PhysicsActor FindPhysicsActor(UUID uuid)
{
SceneObjectPart sop = m_scene.GetSceneObjectPart(uuid);
if (sop != null)
{
return sop.PhysActor;
}
ScenePresence sp = m_scene.GetScenePresence(uuid);
if (sp != null)
{
return sp.PhysicsActor;
}
return null;
}
public void SendPhysUpdateAttributes(PhysicsActor pa)
{
// m_log.DebugFormat("{0}: sending PhysUpdateAttributes for {1}", LogHeader, pa.UUID);
OSDMap data = new OSDMap(15);
data["time"] = OSD.FromString(DateTime.Now.ToString("yyyyMMddHHmmssfff"));
data["localID"] = OSD.FromUInteger(pa.LocalID);
data["uuid"] = OSD.FromUUID(pa.UUID);
data["actorID"] = OSD.FromString(RegionSyncServerModule.ActorID);
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["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["buoyancy"] = OSD.FromReal(pa.Buoyancy);
// data["isColliding"] = OSD.FromBoolean(pa.IsColliding);
// data["isCollidingGround"] = OSD.FromBoolean(pa.CollidingGround);
RegionSyncMessage rsm = new RegionSyncMessage(RegionSyncMessage.MsgType.PhysUpdateAttributes,
OSDParser.SerializeJsonString(data));
Send(rsm);
return;
}
//For simplicity, we assume the subscription sent by PhysEngine is legistimate (no overlapping with other script engines, etc)
private void HandleQuarkSubscription(RegionSyncMessage msg)
{
string quarkString = Encoding.ASCII.GetString(msg.Data, 0, msg.Length);
m_log.Debug(LogHeader + ": received quark-string: " + quarkString);
List<string> quarkStringList = RegionSyncUtil.QuarkStringToStringList(quarkString);
//m_quarkSubscriptions = RegionSyncUtil.GetQuarkInfoList(quarkStringList, QuarkInfo.SizeX, QuarkInfo.SizeY);
List<QuarkInfo> quarkList = RegionSyncUtil.GetQuarkInfoList(quarkStringList);
m_syncServer.RegisterQuarkSubscription(quarkList, this);
m_quarkSubscriptions = new Dictionary<string, QuarkInfo>();
foreach (QuarkInfo quark in quarkList)
{
m_quarkSubscriptions.Add(quark.QuarkStringRepresentation, quark);
}
}
private RegionSyncMessage PrepareObjectUpdateMessage(RegionSyncMessage.MsgType msgType, SceneObjectGroup sog)
{
OSDMap data = new OSDMap(3);
data["locX"] = OSD.FromUInteger(m_scene.RegionInfo.RegionLocX);
data["locY"] = OSD.FromUInteger(m_scene.RegionInfo.RegionLocY);
string sogxml = SceneObjectSerializer.ToXml2Format(sog);
data["sogXml"] = OSD.FromString(sogxml);
RegionSyncMessage rsm = new RegionSyncMessage(msgType, OSDParser.SerializeJsonString(data));
return rsm;
}
private void SendSceneLoc()
{
uint locX = m_scene.RegionInfo.RegionLocX;
uint locY = m_scene.RegionInfo.RegionLocY;
OSDMap data = new OSDMap(2);
data["locX"] = OSD.FromUInteger(locX);
data["locY"] = OSD.FromUInteger(locY);
Send(new RegionSyncMessage(RegionSyncMessage.MsgType.SceneLocation, OSDParser.SerializeJsonString(data)));
}
public void Send(RegionSyncMessage msg)
{
if (msg.Type == RegionSyncMessage.MsgType.AvatarAppearance)
m_log.WarnFormat("{0} Sending AvatarAppearance to client manager", LogHeader);
Send(msg.ToBytes());
}
private void Send(byte[] data)
{
if (m_tcpclient.Connected)
{
try
{
lock (stats)
{
msgsOut++;
bytesOut += data.Length;
}
m_tcpclient.GetStream().BeginWrite(data, 0, data.Length, ar =>
{
if (m_tcpclient.Connected)
{
try
{
m_tcpclient.GetStream().EndWrite(ar);
}
catch (Exception)
{
m_log.WarnFormat("{0} Write to output stream failed", LogHeader);
}
}
}, null);
}
catch (IOException)
{
m_log.WarnFormat("{0} Physics Engine has disconnected.", LogHeader);
}
}
else
{
m_log.DebugFormat("{0} Attempt to send with no connection", LogHeader);
}
}
public void SendObjectUpdate(RegionSyncMessage.MsgType msgType, SceneObjectGroup sog)
{
Send(PrepareObjectUpdateMessage(msgType, sog));
}
#endregion Send/Receive messages to/from the remote Physics Engine
#region Spacial query functions (should be eventually implemented within Scene)
/*
//This should be a function of Scene, but since we don't have the quark concept in Scene yet,
//for now we implement it here.
//Ideally, for quark based space representation, the Scene has a list of quarks, and each quark points
//to a list of objects within that quark. Then it's much easier to return the right set of objects within
//a certain space. (Or use DB that supports spatial queries.)
List<SceneObjectGroup> GetObjectsInGivenSpace(Scene scene, Dictionary<string, QuarkInfo> quarkSubscriptions)
{
List<EntityBase> entities = m_scene.GetEntities();
List<SceneObjectGroup> sogList = new List<SceneObjectGroup>();
foreach (EntityBase e in entities)
{
if (e is SceneObjectGroup)
{
SceneObjectGroup sog = (SceneObjectGroup)e;
string quarkID = RegionSyncUtil.GetQuarkIDByPosition(sog.AbsolutePosition);
if (m_quarkSubscriptions.ContainsKey(quarkID))
{
sogList.Add(sog);
}
}
}
return sogList;
}
*/
#endregion
#region Load balancing functions
/*
public void SendLoadBalanceRejection(string response)
{
RegionSyncMessage msg = new RegionSyncMessage(RegionSyncMessage.MsgType.LoadBalanceRejection, response);
Send(msg);
}
*/
#endregion
}
}

View File

@ -1,765 +0,0 @@
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Collections.Generic;
using System.Threading;
using OpenSim.Framework;
using OpenSim.Region.CoreModules.Framework.InterfaceCommander;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.Framework.Interfaces;
using log4net;
using OpenMetaverse;
using OpenMetaverse.StructuredData;
using OpenSim.Region.Framework.Scenes.Serialization;
using OpenSim.Region.Physics.Manager;
namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
{
//Information of a registered idle physics engine.
//Note, this is a temporary solution to inlcude idle physics engines here.
//In the future, there might be a independent load balaner that keeps track
//of available idle hardware.
public class IdlePhysEngineInfo
{
public TcpClient TClient;
//public IPAddress PhysEngineIPAddr;
//public int PhysEnginePort;
public string ID;
//Will be used to store the overloaded PE that has send LB request and paired with this idle PE
public SceneToPhysEngineConnector AwaitOverloadedSE=null;
public IdlePhysEngineInfo(TcpClient tclient)
{
if(tclient==null) return;
TClient = tclient;
IPAddress ipAddr = ((IPEndPoint)tclient.Client.RemoteEndPoint).Address;
int port = ((IPEndPoint)tclient.Client.RemoteEndPoint).Port;
ID = ipAddr.ToString()+":"+port;
}
}
//Here is the per actor type listening server for physics Engines.
public class SceneToPhysEngineSyncServer : ISceneToPhysEngineServer, ICommandableModule
{
#region SceneToPhysEngineSyncServer members
// Set the addr and port for TcpListener
private IPAddress m_addr;
private Int32 m_port;
//this field is only meaning for the QuarkInfo records on the Scene side
private SceneToPhysEngineConnector m_peConnector=null;
public SceneToPhysEngineConnector PEConnector
{
get { return m_peConnector; }
set { m_peConnector = value; }
}
private int peCounter;
// static counters that are used to compute global configuration state
private static int m_syncServerInitialized = 0;
private static int m_totalConnections = 0;
private static List<Scene> m_allScenes = new List<Scene>();
// The local scene.
private Scene m_scene;
private ILog m_log;
// The listener and the thread which listens for connections from client managers
private TcpListener m_listener;
private Thread m_listenerThread;
private object m_physEngineConnector_lock = new object();
//private Dictionary<string, SceneToPhysEngineConnector> m_physEngineConnectors = new Dictionary<string, SceneToPhysEngineConnector>();
private List<SceneToPhysEngineConnector> m_physEngineConnectors = new List<SceneToPhysEngineConnector>();
// the last connector created
private SceneToPhysEngineConnector m_sceneToPhysEngineConnector = null;
//list of idle physics engines that have registered.
private List<IdlePhysEngineInfo> m_idlePhysEngineList = new List<IdlePhysEngineInfo>();
//List of all quarks, each using the concatenation of x,y values of its left-bottom corners,
// where the x,y values are the offset position in the scene.
private Dictionary<string, QuarkInfo> m_quarksInScene = new Dictionary<string, QuarkInfo>();
private string LogHeader = "[SCENE TO PHYS ENGINE SYNC SERVER]";
//Quark related info
//private int QuarkInfo.SizeX;
//private int QuarkInfo.SizeY;
#region ICommandableModule Members
private readonly Commander m_commander = new Commander("phys");
public ICommander CommandInterface
{
get { return m_commander; }
}
private void InstallInterfaces()
{
// Command cmdSyncStart = new Command("start", CommandIntentions.COMMAND_HAZARDOUS, SyncStart, "Begins synchronization with RegionSyncServer.");
//cmdSyncStart.AddArgument("server_port", "The port of the server to synchronize with", "Integer");
// Command cmdSyncStop = new Command("stop", CommandIntentions.COMMAND_HAZARDOUS, SyncStop, "Stops synchronization with RegionSyncServer.");
//cmdSyncStop.AddArgument("server_address", "The IP address of the server to synchronize with", "String");
//cmdSyncStop.AddArgument("server_port", "The port of the server to synchronize with", "Integer");
Command cmdSyncStatus = new Command("status", CommandIntentions.COMMAND_HAZARDOUS, SyncStatus, "Displays synchronization status.");
//The following two commands are more for easier debugging purpose
// Command cmdSyncSetQuarks = new Command("quarkSpace", CommandIntentions.COMMAND_HAZARDOUS, SetQuarkList, "Set the set of quarks to subscribe to. For debugging purpose. Should be issued before \"sync start\"");
// cmdSyncSetQuarks.AddArgument("quarkSpace", "The (rectangle) space of quarks to subscribe, represented by x0_y0,x1_y1, the left-bottom and top-right corners of the rectangel space", "String");
// Command cmdSyncSetQuarkSize = new Command("quarksize", CommandIntentions.COMMAND_HAZARDOUS, SetQuarkSize, "Set the size of each quark. For debugging purpose. Should be issued before \"sync quarks\"");
// cmdSyncSetQuarkSize.AddArgument("quarksizeX", "The size on x axis of each quark", "Integer");
// cmdSyncSetQuarkSize.AddArgument("quarksizeY", "The size on y axis of each quark", "Integer");
// m_commander.RegisterCommand("start", cmdSyncStart);
// m_commander.RegisterCommand("stop", cmdSyncStop);
m_commander.RegisterCommand("status", cmdSyncStatus);
// m_commander.RegisterCommand("quarkSpace", cmdSyncSetQuarks);
lock (m_scene)
{
// Add this to our scene so scripts can call these functions
m_scene.RegisterModuleCommander(m_commander);
}
}
/// <summary>
/// Processes commandline input. Do not call directly.
/// </summary>
/// <param name="args">Commandline arguments</param>
private void EventManager_OnPluginConsole(string[] args)
{
if (args[0] == "phys")
{
if (args.Length == 1)
{
m_commander.ProcessConsoleCommand("help", new string[0]);
return;
}
string[] tmpArgs = new string[args.Length - 2];
int i;
for (i = 2; i < args.Length; i++)
tmpArgs[i - 2] = args[i];
m_commander.ProcessConsoleCommand(args[1], tmpArgs);
}
}
private void SyncStart(Object[] args)
{
return;
}
private void SyncStop(Object[] args)
{
return;
}
private void SyncStatus(Object[] args)
{
lock (m_physEngineConnector_lock)
{
if (m_physEngineConnectors.Count == 0)
{
m_log.Warn(LogHeader + " Not currently synchronized");
return;
}
m_log.Warn(LogHeader + " Synchronized");
foreach (SceneToPhysEngineConnector pec in m_physEngineConnectors)
{
m_log.Warn(pec.GetStats());
}
}
}
#endregion
// Check if any of the client views are in a connected state
public bool IsPhysEngineScene() { return SceneToPhysEngineSyncServer.IsPhysEngineScene2S(); }
public bool IsActivePhysEngineScene() { return SceneToPhysEngineSyncServer.IsActivePhysEngineScene2S(); }
public bool IsPhysEngineActor() { return SceneToPhysEngineSyncServer.IsPhysEngineActorS; }
public bool Synced
{
get { return (m_physEngineConnectors.Count > 0); }
}
public static bool IsPhysEngineSceneS
{
get { return (SceneToPhysEngineSyncServer.m_syncServerInitialized > 0); }
}
public static bool IsPhysEngineScene2S()
{
return (SceneToPhysEngineSyncServer.m_syncServerInitialized > 0);
}
public static bool IsActivePhysEngineSceneS
{
get {
System.Console.WriteLine("IsActivePhysEngineScene: si={0} tc={1}",
SceneToPhysEngineSyncServer.m_syncServerInitialized,
SceneToPhysEngineSyncServer.m_totalConnections);
return (SceneToPhysEngineSyncServer.m_syncServerInitialized > 0
&& SceneToPhysEngineSyncServer.m_totalConnections > 0);
}
}
public static bool IsActivePhysEngineScene2S()
{
return (SceneToPhysEngineSyncServer.m_syncServerInitialized > 0
&& SceneToPhysEngineSyncServer.m_totalConnections > 0);
}
public static bool IsPhysEngineActorS
{
get { return PhysEngineToSceneConnectorModule.IsPhysEngineActorS; }
}
/// <summary>
/// The scene is unknown by ODE so we have to look through the scenes to
/// find the one with this PhysicsActor so we can send the update.
/// </summary>
/// <param name="pa"></param>
public static void RouteUpdate(PhysicsActor pa)
{
SceneObjectPart sop = null;
Scene s = null;
foreach (Scene ss in m_allScenes)
{
try
{
sop = ss.GetSceneObjectPart(pa.UUID);
}
catch
{
sop = null;
}
if (sop != null)
{
s = ss;
break;
}
else
{
ScenePresence sp = ss.GetScenePresence(pa.UUID);
if (sp != null)
{
s = ss;
break;
}
}
}
if (s != null)
{
if (s.SceneToPhysEngineSyncServer != null)
{
s.SceneToPhysEngineSyncServer.SendUpdate(pa);
}
else
{
Console.WriteLine("RouteUpdate: SceneToPhysEngineSyncServer is not available");
}
}
else
{
Console.WriteLine("RouteUpdate: no SOP for update of {0}", pa.UUID);
}
return;
}
public void SendUpdate(PhysicsActor pa)
{
// m_log.DebugFormat("{0}: SendUpdate for {1}", LogHeader, pa.LocalID);
if (m_sceneToPhysEngineConnector != null)
{
this.m_sceneToPhysEngineConnector.SendPhysUpdateAttributes(pa);
}
}
#endregion
// Constructor
public SceneToPhysEngineSyncServer(Scene scene, string addr, int port)
{
if (QuarkInfo.SizeX == -1 || QuarkInfo.SizeY == -1)
{
m_log.Error(LogHeader + " QuarkInfo.SizeX or QuarkInfo.SizeY has not been configured yet.");
Environment.Exit(0); ;
}
m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
//m_log.Warn(LogHeader + "Constructed");
m_scene = scene;
m_addr = IPAddress.Parse(addr);
m_port = port;
m_scene.RegisterModuleInterface<ISceneToPhysEngineServer>(this);
// remember all the scenes that are configured for connection to physics engine
if (!m_allScenes.Contains(m_scene))
{
m_allScenes.Add(m_scene);
}
InitQuarksInScene();
SubscribeToEvents();
m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole;
InstallInterfaces();
}
private void SubscribeToEvents()
{
}
private void UnSubscribeToEvents()
{
}
// Start the server
public void Start()
{
SceneToPhysEngineSyncServer.m_syncServerInitialized++;
m_listenerThread = new Thread(new ThreadStart(Listen));
m_listenerThread.Name = "SceneToPhysEngineSyncServer Listener";
m_log.DebugFormat("{0}: Starting {1} thread", LogHeader, m_listenerThread.Name);
m_listenerThread.Start();
// m_log.DebugFormat("{0}: Started", LogHeader);
}
// Stop the server and disconnect all RegionSyncClients
public void Shutdown()
{
m_log.DebugFormat("{0}: Shutdown", LogHeader);
SceneToPhysEngineSyncServer.m_syncServerInitialized--;
// Stop the listener and listening thread so no new clients are accepted
m_listener.Stop();
m_listenerThread.Abort();
m_listenerThread = null;
// Stop all existing SceneTOSEConnectors
//TO FINISH
foreach (SceneToPhysEngineConnector peConnector in m_physEngineConnectors)
{
peConnector.Shutdown();
}
m_physEngineConnectors.Clear();
UnSubscribeToEvents();
}
private void InitQuarksInScene()
{
List<QuarkInfo> quarkList = RegionSyncUtil.GetAllQuarksInScene();
foreach (QuarkInfo quark in quarkList)
{
m_quarksInScene.Add(quark.QuarkStringRepresentation, quark);
}
}
public void RegisterQuarkSubscription(List<QuarkInfo> quarkSubscriptions, SceneToPhysEngineConnector peConnector)
{
foreach (QuarkInfo quark in quarkSubscriptions)
{
string quarkID = quark.QuarkStringRepresentation;
// TODO: does the physics engine connect to quarks. Next line commented out.
// m_quarksInScene[quarkID].PEConnector = peConnector;
m_log.Debug(LogHeader + ": " + quarkID + " subscribed by "+peConnector.Description);
}
}
// Add a connector to a physics engine
public void AddSyncedPhysEngine(SceneToPhysEngineConnector peConnector)
{
lock (m_physEngineConnector_lock)
{
m_physEngineConnectors.Add(peConnector);
m_sceneToPhysEngineConnector = peConnector;
}
}
// Remove the client view from the list and decrement synced client counter
public void RemoveSyncedPhysEngine(SceneToPhysEngineConnector peConnector)
{
lock (m_physEngineConnector_lock)
{
//Dictionary<string, SceneToPhysEngineConnector> currentlist = m_physEngineConnectors;
//Dictionary<string, SceneToPhysEngineConnector> newlist = new Dictionary<string, SceneToPhysEngineConnector>(currentlist);
m_physEngineConnectors.Remove(peConnector);
// Threads holding the previous version of the list can keep using it since
// they will not hold it for long and get a new copy next time they need to iterate
//m_physEngineConnectors = newlist;
}
}
// Listen for connections from a new RegionSyncClient
// When connected, start the ReceiveLoop for the new client
private void Listen()
{
m_listener = new TcpListener(m_addr, m_port);
try
{
// Start listening for clients
m_listener.Start();
while (true)
{
// *** Move/Add TRY/CATCH to here, but we don't want to spin loop on the same error
m_log.WarnFormat(LogHeader + ": Listening for new connections on port {0}...", m_port.ToString());
TcpClient tcpclient = m_listener.AcceptTcpClient();
IPAddress addr = ((IPEndPoint)tcpclient.Client.RemoteEndPoint).Address;
int port = ((IPEndPoint)tcpclient.Client.RemoteEndPoint).Port;
SceneToPhysEngineSyncServer.m_totalConnections++;
// m_log.DebugFormat("{0}: m_totalConnections = {1}", LogHeader, SceneToPhysEngineSyncServer.m_totalConnections);
ActorStatus actorStatus = GetActorStatus(tcpclient);
switch (actorStatus)
{
case ActorStatus.Sync:
// Add the SceneToPhysEngineConnector to the list
SceneToPhysEngineConnector sceneToPEConnector = new SceneToPhysEngineConnector(++peCounter, m_scene, tcpclient, this);
AddSyncedPhysEngine(sceneToPEConnector);
break;
case ActorStatus.Idle:
IdlePhysEngineInfo idleSE = new IdlePhysEngineInfo(tcpclient);
m_log.DebugFormat("{0}: adding an idle SE ({1}:{2})", LogHeader, addr, port);
m_idlePhysEngineList.Add(idleSE);
break;
default:
m_log.DebugFormat("{0}: Unknown actor status", LogHeader);
break;
}
}
}
catch (SocketException e)
{
m_log.WarnFormat("{0}: [Listen] SocketException: {1}", LogHeader, e);
}
}
/*
public void RegisterSyncedPhysEngine(SceneToPhysEngineConnector sceneToSEConnector)
{
//first, remove it from the idle list
m_idlePhysEngineList.Remove(sceneToSEConnector);
//now, added to the synced SE list
AddSyncedPhysEngine(sceneToSEConnector);
}
* */
// Broadcast a message to all connected RegionSyncClients
public void SendToAllConnectedPE(RegionSyncMessage msg)
{
if (m_physEngineConnectors.Count > 0)
{
m_log.Debug(LogHeader + ": region " + m_scene.RegionInfo.RegionName + " Broadcast to PhysEngine, msg " + msg.Type);
foreach (SceneToPhysEngineConnector peConnector in m_physEngineConnectors)
{
peConnector.Send(msg);
}
}
}
//TO FINISH: Find the right SceneToSEConnector to forward the message
public void SendToPE(RegionSyncMessage.MsgType msgType, SceneObjectGroup sog)
{
SceneToPhysEngineConnector peConnector = GetSceneToPEConnector(sog);
if (peConnector != null)
{
peConnector.SendObjectUpdate(msgType, sog);
}
}
//This is to send a message, rsm, to phys engine, and the message is about object SOG. E.g. RemovedObject
public void SendToPE(RegionSyncMessage rsm, SceneObjectGroup sog)
{
SceneToPhysEngineConnector peConnector = GetSceneToPEConnector(sog);
if (peConnector != null)
{
peConnector.Send(rsm);
}
}
private SceneToPhysEngineConnector GetSceneToPEConnector(SceneObjectGroup sog)
{
if (m_physEngineConnectors.Count == 0)
return null;
if (sog == null)
{
return m_physEngineConnectors[0];
}
else
{
//Find the right SceneToSEConnector by the object's position
//TO FINISH: Map the object to a quark first, then map the quark to SceneToSEConnector
string quarkID = RegionSyncUtil.GetQuarkIDByPosition(sog.AbsolutePosition);
// TODO: connection of physics engine to quarks. Next line commented out
// SceneToPhysEngineConnector peConnector = m_quarksInScene[quarkID].PEConnector;
if (PEConnector == null)
{
m_log.Warn(LogHeader + sog.AbsolutePosition.ToString() + " not covered by any physics engine");
}
return PEConnector;
}
}
private ActorStatus GetActorStatus(TcpClient tcpclient)
{
m_log.Debug(LogHeader+ ": Get Actor status");
RegionSyncMessage msg = new RegionSyncMessage(tcpclient.GetStream());
ActorStatus actorStatus;
switch (msg.Type)
{
case RegionSyncMessage.MsgType.ActorStatus:
{
string status = Encoding.ASCII.GetString(msg.Data, 0, msg.Length);
m_log.Debug(LogHeader + ": recv status: " + status);
actorStatus = (ActorStatus)Convert.ToInt32(status);
break;
}
default:
{
m_log.Error(LogHeader + ": Expect Message Type: ActorStatus");
RegionSyncMessage.HandleError("[REGION SYNC SERVER]", msg, String.Format("{0} Expect Message Type: ActorType", "[REGION SYNC SERVER]"));
return ActorStatus.Null;
}
}
return actorStatus;
}
#region Event Handlers
#endregion Event Handlers
#region Load balancing members and functions
/*
//keep track of idle physics engines that are in the process of load balancing (they are off the idle list, but not a working physics engine yet (not sync'ing with Scene yet)).
private Dictionary<string, IdlePhysEngineInfo> m_loadBalancingIdleSEs = new Dictionary<string,IdlePhysEngineInfo>();
public void HandleLoadBalanceRequest(SceneToPhysEngineConnector seConnctor)
{
//Let's start a thread to do the job, so that we can return quickly and don't block on ReceiveLoop()
Thread partitionThread = new Thread(new ParameterizedThreadStart(TriggerLoadBalanceProcess));
partitionThread.Name = "TriggerLoadBalanceProcess";
partitionThread.Start((object)seConnctor);
}
public void TriggerLoadBalanceProcess(object arg)
{
SceneToPhysEngineConnector seConnctor = (SceneToPhysEngineConnector)arg;
IdlePhysEngineInfo idlePhysEngineInfo = GetIdlePhysEngineConnector();
if (idlePhysEngineInfo != null)
{
RegionSyncMessage msg = new RegionSyncMessage(RegionSyncMessage.MsgType.LoadMigrationNotice);
Send(idlePhysEngineInfo.TClient, msg.ToBytes());
m_log.Debug(LogHeader + ": HandleLoadBalanceRequest from " + seConnctor.Description + ", picked idle SE: " + idlePhysEngineInfo.ID);
//keep track of which overload physics engine is paired up with which idle physics engine
idlePhysEngineInfo.AwaitOverloadedSE = seConnctor;
m_loadBalancingIdleSEs.Add(idlePhysEngineInfo.ID, idlePhysEngineInfo);
m_log.Debug("ToSEConnector portal: local -" +
((IPEndPoint)idlePhysEngineInfo.TClient.Client.LocalEndPoint).Address.ToString() + ":" + ((IPEndPoint)idlePhysEngineInfo.TClient.Client.LocalEndPoint).Port
+ "; remote - " + ((IPEndPoint)idlePhysEngineInfo.TClient.Client.RemoteEndPoint).Address.ToString() + ":"
+ ((IPEndPoint)idlePhysEngineInfo.TClient.Client.RemoteEndPoint).Port);
//Now we expect the idle physics engine to reply back
msg = new RegionSyncMessage(idlePhysEngineInfo.TClient.GetStream());
if (msg.Type != RegionSyncMessage.MsgType.LoadMigrationListenerInitiated)
{
m_log.Warn(LogHeader + ": should receive a message of type LoadMigrationListenerInitiated, but received " + msg.Type.ToString());
}
else
{
//Before the load is migrated from overloaded physics engine to the idle engine, sync with the DB to update the state in DB
List<EntityBase> entities = m_scene.GetEntities();
foreach (EntityBase entity in entities)
{
if (!entity.IsDeleted && entity is SceneObjectGroup && ((SceneObjectGroup)entity).HasGroupChanged)
{
m_scene.ForceSceneObjectBackup((SceneObjectGroup)entity);
}
}
OSDMap data = DeserializeMessage(msg);
if (!data.ContainsKey("ip") || !data.ContainsKey("port") )
{
m_log.Warn(LogHeader + ": parameters missing in SceneLocation message from Scene, need to have ip, port");
return;
}
//echo the information back to the overloaded physics engine
seConnctor.Send(new RegionSyncMessage(RegionSyncMessage.MsgType.LoadBalanceResponse, OSDParser.SerializeJsonString(data)));
m_log.Debug(LogHeader + " now remove physics engine " + idlePhysEngineInfo.ID + " from idle SE list, and create SceneToPhysEngineConnector to it");
//create a SceneToSEConnector for the idle physics engine, who will be sync'ing with this SyncServer soon
SceneToPhysEngineConnector sceneToSEConnector = new SceneToPhysEngineConnector(++peCounter, m_scene, idlePhysEngineInfo.TClient, this);
//Now remove the physics engine from the idle SE list
m_idlePhysEngineList.Remove(idlePhysEngineInfo);
//AddSyncedPhysEngine(sceneToSEConnector);
}
}
else
{
seConnctor.SendLoadBalanceRejection("no idle physics engines");
}
}
*/
HashSet<string> exceptions = new HashSet<string>();
private OSDMap DeserializeMessage(RegionSyncMessage msg)
{
OSDMap data = null;
try
{
data = OSDParser.DeserializeJson(Encoding.ASCII.GetString(msg.Data, 0, msg.Length)) as OSDMap;
}
catch (Exception e)
{
lock (exceptions)
// If this is a new message, then print the underlying data that caused it
if (!exceptions.Contains(e.Message))
m_log.Error(LogHeader + " " + Encoding.ASCII.GetString(msg.Data, 0, msg.Length));
data = null;
}
return data;
}
private void Send(TcpClient tcpclient, byte[] data)
{
if (tcpclient.Connected)
{
try
{
tcpclient.GetStream().BeginWrite(data, 0, data.Length, ar =>
{
if (tcpclient.Connected)
{
try
{
tcpclient.GetStream().EndWrite(ar);
}
catch (Exception)
{ }
}
}, null);
}
catch (IOException)
{
m_log.WarnFormat("{0} physics Engine has disconnected.", LogHeader);
}
}
}
private IdlePhysEngineInfo GetIdlePhysEngineConnector()
{
if (m_idlePhysEngineList.Count == 0)
return null;
IdlePhysEngineInfo idleSEInfo = m_idlePhysEngineList[0];
m_idlePhysEngineList.Remove(idleSEInfo);
return idleSEInfo;
}
#endregion Load balancing functions
#region Message Logging
public static bool logInput = false;
public static bool logOutput = true;
public static bool logEnabled = true;
private class PhysMsgLogger
{
public DateTime startTime;
public string path = null;
public System.IO.TextWriter Log = null;
}
private static PhysMsgLogger logWriter = null;
private static TimeSpan logMaxFileTime = new TimeSpan(0, 5, 0); // (h,m,s) => 5 minutes
public static string logDir = "/stats/stats";
private static object logLocker = new Object();
public static void PhysLogMessage(bool direction, RegionSyncMessage rsm)
{
if (!logEnabled) return; // save to work of the ToStringFull if not enabled
PhysLogMessage(direction, rsm.ToStringFull());
}
/// <summary>
/// Log a physics bucket message
/// </summary>
/// <param name="direction">True of message originated from the agent</param>
/// <param name="msg">the message to log</param>
public static void PhysLogMessage(bool direction, string msg)
{
if (!logEnabled) return;
lock (logLocker)
{
try
{
DateTime now = DateTime.Now;
if (logWriter == null || (now > logWriter.startTime + logMaxFileTime))
{
if (logWriter != null && logWriter.Log != null)
{
logWriter.Log.Close();
logWriter.Log.Dispose();
logWriter.Log = null;
}
// First log file or time has expired, start writing to a new log file
logWriter = new PhysMsgLogger();
logWriter.startTime = now;
logWriter.path = (logDir.Length > 0 ? logDir + System.IO.Path.DirectorySeparatorChar.ToString() : "")
+ String.Format("physics-{0}.log", now.ToString("yyyyMMddHHmmss"));
logWriter.Log = new StreamWriter(File.Open(logWriter.path, FileMode.Append, FileAccess.Write));
}
if (logWriter != null && logWriter.Log != null)
{
StringBuilder buff = new StringBuilder();
buff.Append(now.ToString("yyyyMMddHHmmssfff"));
buff.Append(" ");
buff.Append(direction ? "A->S:" : "S->A:");
buff.Append(msg);
buff.Append("\r\n");
logWriter.Log.Write(buff.ToString());
}
}
catch (Exception e)
{
// m_log.ErrorFormat("{0}: FAILURE WRITING TO LOGFILE: {1}", LogHeader, e);
logEnabled = false;
}
}
return;
}
public static void PhysLogMessageClose()
{
if (logWriter != null && logWriter.Log != null)
{
logWriter.Log.Close();
logWriter.Log.Dispose();
logWriter.Log = null;
logWriter = null;
}
logEnabled = false;
}
#endregion Message Logging
}
}

View File

@ -144,7 +144,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
#endregion //IDSGActorSyncModule #endregion //IDSGActorSyncModule
#region PhysicsEngineSyncModule memebers and functions #region PhysicsEngineSyncModule members and functions
private ILog m_log; private ILog m_log;
private bool m_active = false; private bool m_active = false;
public bool Active public bool Active
@ -172,6 +172,6 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
m_scene.DeleteAllSceneObjects(); m_scene.DeleteAllSceneObjects();
} }
#endregion //ScriptEngineSyncModule #endregion PhysicsEngineSyncModule members and functions
} }
} }

View File

@ -236,6 +236,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
sog.UpdateTaintedBucketSyncInfo(bucketName, DateTime.Now.Ticks); //this update the timestamp and clear the taint info of the bucket sog.UpdateTaintedBucketSyncInfo(bucketName, DateTime.Now.Ticks); //this update the timestamp and clear the taint info of the bucket
string sogxml = SceneObjectSerializer.ToXml2Format(sog); string sogxml = SceneObjectSerializer.ToXml2Format(sog);
SymmetricSyncMessage syncMsg = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.UpdatedObject, sogxml); SymmetricSyncMessage syncMsg = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.UpdatedObject, sogxml);
m_log.DebugFormat("{0}: GeneralBucketSender for {1}", LogHeader, sog.UUID);
SendObjectUpdateToRelevantSyncConnectors(sog, syncMsg); SendObjectUpdateToRelevantSyncConnectors(sog, syncMsg);
} }
} }
@ -246,6 +247,10 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
{ {
updatedPart.UpdateTaintedBucketSyncInfo(bucketName, DateTime.Now.Ticks); updatedPart.UpdateTaintedBucketSyncInfo(bucketName, DateTime.Now.Ticks);
Physics.Manager.PhysicsActor pa = updatedPart.PhysActor;
if (pa == null)
return;
OSDMap data = new OSDMap(); OSDMap data = new OSDMap();
data["UUID"] = OSD.FromUUID(updatedPart.UUID); data["UUID"] = OSD.FromUUID(updatedPart.UUID);
@ -253,27 +258,29 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
data["GroupPosition"] = OSD.FromVector3(updatedPart.GroupPosition); data["GroupPosition"] = OSD.FromVector3(updatedPart.GroupPosition);
data["OffsetPosition"] = OSD.FromVector3(updatedPart.OffsetPosition); data["OffsetPosition"] = OSD.FromVector3(updatedPart.OffsetPosition);
data["RotationOffset"] = OSD.FromQuaternion(updatedPart.RotationOffset);
data["Velocity"] = OSD.FromVector3(updatedPart.Velocity);
data["Scale"] = OSD.FromVector3(updatedPart.Scale); data["Scale"] = OSD.FromVector3(updatedPart.Scale);
//Other properties to be included data["AngularVelocity"] = OSD.FromVector3(updatedPart.AngularVelocity);
/* data["RotationOffset"] = OSD.FromQuaternion(updatedPart.RotationOffset);
"Position": data["Size"] = OSD.FromVector3(pa.Size);
"Size": data["Position"] = OSD.FromVector3(pa.Position);
"Force": data["Force"] = OSD.FromVector3(pa.Force);
"RotationalVelocity": data["Velocity"] = OSD.FromVector3(pa.Velocity);
"PA_Acceleration": data["RotationalVelocity"] = OSD.FromVector3(pa.RotationalVelocity);
"Torque": data["PA_Acceleration"] = OSD.FromVector3(pa.Acceleration);
"Orientation": data["Torque"] = OSD.FromVector3(pa.Torque);
"IsPhysical": data["Orientation"] = OSD.FromQuaternion(pa.Orientation);
"Flying": data["IsPhysical"] = OSD.FromBoolean(pa.IsPhysical);
"Buoyancy": 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["LastUpdateTimeStamp"] = OSD.FromLong(updatedPart.BucketSyncInfoList[bucketName].LastUpdateTimeStamp);
data["LastUpdateActorID"] = OSD.FromString(updatedPart.BucketSyncInfoList[bucketName].LastUpdateActorID); data["LastUpdateActorID"] = OSD.FromString(updatedPart.BucketSyncInfoList[bucketName].LastUpdateActorID);
SymmetricSyncMessage syncMsg = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.UpdatedBucketProperties, OSDParser.SerializeJsonString(data)); SymmetricSyncMessage syncMsg = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.UpdatedBucketProperties, OSDParser.SerializeJsonString(data));
m_log.DebugFormat("{0}: PhysBucketSender for {1}", LogHeader, updatedPart.UUID.ToString());
SendObjectUpdateToRelevantSyncConnectors(updatedPart, syncMsg); SendObjectUpdateToRelevantSyncConnectors(updatedPart, syncMsg);
} }
} }
@ -300,19 +307,22 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
case SceneObjectPartProperties.GroupPosition: case SceneObjectPartProperties.GroupPosition:
case SceneObjectPartProperties.OffsetPosition: case SceneObjectPartProperties.OffsetPosition:
case SceneObjectPartProperties.Scale: case SceneObjectPartProperties.Scale:
case SceneObjectPartProperties.Velocity:
case SceneObjectPartProperties.AngularVelocity: case SceneObjectPartProperties.AngularVelocity:
case SceneObjectPartProperties.RotationOffset: case SceneObjectPartProperties.RotationOffset:
case SceneObjectPartProperties.Position:
case SceneObjectPartProperties.Size: case SceneObjectPartProperties.Size:
case SceneObjectPartProperties.Position:
case SceneObjectPartProperties.Force: case SceneObjectPartProperties.Force:
case SceneObjectPartProperties.Velocity:
case SceneObjectPartProperties.RotationalVelocity: case SceneObjectPartProperties.RotationalVelocity:
case SceneObjectPartProperties.PA_Acceleration: case SceneObjectPartProperties.PA_Acceleration:
case SceneObjectPartProperties.Torque: case SceneObjectPartProperties.Torque:
case SceneObjectPartProperties.Orientation: case SceneObjectPartProperties.Orientation:
case SceneObjectPartProperties.IsPhysical: case SceneObjectPartProperties.IsPhysical:
case SceneObjectPartProperties.Flying: case SceneObjectPartProperties.Flying:
case SceneObjectPartProperties.Kinematic:
case SceneObjectPartProperties.Buoyancy: case SceneObjectPartProperties.Buoyancy:
case SceneObjectPartProperties.IsCollidingGround:
case SceneObjectPartProperties.IsColliding:
m_primPropertyBucketMap.Add(property, physicsBucketName); m_primPropertyBucketMap.Add(property, physicsBucketName);
break; break;
default: default:
@ -1508,7 +1518,8 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
UUID partUUID = data["UUID"].AsUUID(); UUID partUUID = data["UUID"].AsUUID();
string bucketName = data["Bucket"].AsString(); string bucketName = data["Bucket"].AsString();
/* 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(); SceneObjectPart updatedPart = new SceneObjectPart();
updatedPart.GroupPosition = data["GroupPosition"].AsVector3(); updatedPart.GroupPosition = data["GroupPosition"].AsVector3();
updatedPart.OffsetPosition = data["OffsetPosition"].AsVector3(); updatedPart.OffsetPosition = data["OffsetPosition"].AsVector3();
@ -1519,8 +1530,6 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
updatedPart.Shape = new PrimitiveBaseShape(); updatedPart.Shape = new PrimitiveBaseShape();
updatedPart.Scale = data["Scale"].AsVector3(); updatedPart.Scale = data["Scale"].AsVector3();
/*
Dictionary<string, Object> updatedProperties = new Dictionary<string, Object>(); Dictionary<string, Object> updatedProperties = new Dictionary<string, Object>();
updatedProperties.Add("GroupPosition", (Object)data["GroupPosition"].AsVector3()); updatedProperties.Add("GroupPosition", (Object)data["GroupPosition"].AsVector3());
updatedProperties.Add("OffsetPosition", (Object)data["OffsetPosition"].AsVector3()); updatedProperties.Add("OffsetPosition", (Object)data["OffsetPosition"].AsVector3());
@ -1528,9 +1537,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
updatedProperties.Add("Velocity", (Object)data["Velocity"].AsVector3()); updatedProperties.Add("Velocity", (Object)data["Velocity"].AsVector3());
updatedProperties.Add("AngularVelocity", (Object)data["AngularVelocity"].AsVector3()); updatedProperties.Add("AngularVelocity", (Object)data["AngularVelocity"].AsVector3());
updatedProperties.Add("Scale", (Object)data["Scale"].AsVector3()); updatedProperties.Add("Scale", (Object)data["Scale"].AsVector3());
* */ */
//Other properties to be included //Other properties to be included
/* /*
"Position": "Position":
@ -1544,12 +1551,13 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
"Flying": "Flying":
"Buoyancy": "Buoyancy":
* */ * */
BucketSyncInfo rBucketSyncInfo = new BucketSyncInfo(bucketName); BucketSyncInfo rBucketSyncInfo = new BucketSyncInfo(bucketName);
rBucketSyncInfo.LastUpdateTimeStamp = data["LastUpdateTimeStamp"].AsLong(); rBucketSyncInfo.LastUpdateTimeStamp = data["LastUpdateTimeStamp"].AsLong();
rBucketSyncInfo.LastUpdateActorID = data["LastUpdateActorID"].AsString(); rBucketSyncInfo.LastUpdateActorID = data["LastUpdateActorID"].AsString();
updatedPart.BucketSyncInfoList.Add(bucketName, rBucketSyncInfo); // updatedPart.BucketSyncInfoList.Add(bucketName, rBucketSyncInfo);
m_scene.UpdateObjectPartBucketProperties(bucketName, partUUID, updatedPart); m_scene.UpdateObjectPartBucketProperties(bucketName, partUUID, data, rBucketSyncInfo);
} }
private void SendTerrainUpdateMessage() private void SendTerrainUpdateMessage()

View File

@ -816,9 +816,10 @@ namespace OpenSim.Region.Framework.Scenes
} }
//public ObjectUpdateResult UpdateObjectPartBucketProperties(string bucketName, UUID partUUID, Dictionary<string, Object> updatedProperties, BucketSyncInfo rBucketSyncInfo) //public ObjectUpdateResult UpdateObjectPartBucketProperties(string bucketName, UUID partUUID, Dictionary<string, Object> updatedProperties, BucketSyncInfo rBucketSyncInfo)
public ObjectUpdateResult UpdateObjectPartBucketProperties(string bucketName, UUID partUUID, SceneObjectPart updatePart) public ObjectUpdateResult UpdateObjectPartBucketProperties(string bucketName, UUID partUUID,
Object updatePart, BucketSyncInfo bucketSyncInfo)
{ {
return m_sceneGraph.UpdateObjectPartBucketProperties(bucketName, partUUID, updatePart); return m_sceneGraph.UpdateObjectPartBucketProperties(bucketName, partUUID, updatePart, bucketSyncInfo);
} }
#endregion //SYMMETRIC SYNC #endregion //SYMMETRIC SYNC

View File

@ -2430,7 +2430,8 @@ namespace OpenSim.Region.Framework.Scenes
} }
//public Scene.ObjectUpdateResult UpdateObjectPartBucketProperties(string bucketName, UUID partUUID, Dictionary<string, Object> updatedProperties, BucketSyncInfo rBucketSyncInfo) //public Scene.ObjectUpdateResult UpdateObjectPartBucketProperties(string bucketName, UUID partUUID, Dictionary<string, Object> updatedProperties, BucketSyncInfo rBucketSyncInfo)
public Scene.ObjectUpdateResult UpdateObjectPartBucketProperties(string bucketName, UUID partUUID, SceneObjectPart updatedPart) public Scene.ObjectUpdateResult UpdateObjectPartBucketProperties(string bucketName, UUID partUUID,
Object updatedPart, BucketSyncInfo bucketSyncInfo)
{ {
SceneObjectPart localPart = GetSceneObjectPart(partUUID); SceneObjectPart localPart = GetSceneObjectPart(partUUID);
if (localPart == null) if (localPart == null)
@ -2438,7 +2439,7 @@ namespace OpenSim.Region.Framework.Scenes
m_log.Warn("No SOP found: UUID -- " + partUUID); m_log.Warn("No SOP found: UUID -- " + partUUID);
return Scene.ObjectUpdateResult.Unchanged; return Scene.ObjectUpdateResult.Unchanged;
} }
return localPart.UpdateBucketProperties(bucketName, updatedPart); return localPart.UpdateBucketProperties(bucketName, updatedPart, bucketSyncInfo);
} }
#endregion //SYMMETRIC SYNC #endregion //SYMMETRIC SYNC

View File

@ -36,6 +36,7 @@ using System.Xml.Serialization;
using log4net; using log4net;
using OpenMetaverse; using OpenMetaverse;
using OpenMetaverse.Packets; using OpenMetaverse.Packets;
using OpenMetaverse.StructuredData;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes.Scripting; using OpenSim.Region.Framework.Scenes.Scripting;
@ -5158,6 +5159,9 @@ namespace OpenSim.Region.Framework.Scenes
IsPhysical, IsPhysical,
Flying, Flying,
Buoyancy, Buoyancy,
Kinematic,
IsCollidingGround,
IsColliding,
//TODO!!!! To be handled in serialization/deserizaltion for synchronization //TODO!!!! To be handled in serialization/deserizaltion for synchronization
AggregateScriptEvents, AggregateScriptEvents,
IsSelected, IsSelected,
@ -5204,7 +5208,7 @@ namespace OpenSim.Region.Framework.Scenes
private static string m_localActorID = ""; private static string m_localActorID = "";
//private static int m_bucketCount = 0; //private static int m_bucketCount = 0;
//private delegate void BucketUpdateProcessor(int bucketIndex); //private delegate void BucketUpdateProcessor(int bucketIndex);
private delegate void BucketUpdateProcessor(SceneObjectPart updatedPart, string bucketName); private delegate void BucketUpdateProcessor(Object updatedPart, string bucketName);
//private static Dictionary<string, BucketUpdateProcessor> m_bucketUpdateProcessors = new Dictionary<string, BucketUpdateProcessor>(); //private static Dictionary<string, BucketUpdateProcessor> m_bucketUpdateProcessors = new Dictionary<string, BucketUpdateProcessor>();
private Dictionary<string, BucketUpdateProcessor> m_bucketUpdateProcessors = new Dictionary<string, BucketUpdateProcessor>(); private Dictionary<string, BucketUpdateProcessor> m_bucketUpdateProcessors = new Dictionary<string, BucketUpdateProcessor>();
@ -5338,8 +5342,11 @@ namespace OpenSim.Region.Framework.Scenes
} }
} }
private void GeneralBucketUpdateProcessor(SceneObjectPart updatedPart, string bucketName) private void GeneralBucketUpdateProcessor(Object updatedPartO, string bucketName)
{ {
if (!(updatedPartO is SceneObjectPart)) return;
SceneObjectPart updatedPart = (SceneObjectPart)updatedPartO;
//If needed, we could define new set functions for these properties, and cast this SOP to SOPBase to //If needed, we could define new set functions for these properties, and cast this SOP to SOPBase to
//invoke the set functions in SOPBase //invoke the set functions in SOPBase
//SceneObjectPartBase localPart = (SceneObjectPartBase)this; //SceneObjectPartBase localPart = (SceneObjectPartBase)this;
@ -5429,37 +5436,46 @@ namespace OpenSim.Region.Framework.Scenes
//NOTE: only touch the properties and BucketSyncInfo that is related to the given bucketName. Other properties and //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". //buckets may not be filled at all in "updatedPart".
private void PhysicsBucketUpdateProcessor(SceneObjectPart updatedPart, string bucketName) private void PhysicsBucketUpdateProcessor(Object updatedPartO, string bucketName)
{ {
if (!(updatedPartO is OSDMap)) return;
OSDMap data = (OSDMap)updatedPartO;
//If needed, we could define new set functions for these properties, and cast this SOP to SOPBase to //If needed, we could define new set functions for these properties, and cast this SOP to SOPBase to
//invoke the set functions in SOPBase //invoke the set functions in SOPBase
//SceneObjectPartBase localPart = (SceneObjectPartBase)this; //SceneObjectPartBase localPart = (SceneObjectPartBase)this;
SceneObjectPart localPart = this; SceneObjectPart localPart = this;
PhysicsActor pa = localPart.PhysActor;
lock (m_bucketUpdateLocks[bucketName]) lock (m_bucketUpdateLocks[bucketName])
{ {
localPart.GroupPosition = updatedPart.GroupPosition; localPart.GroupPosition = data["GroupPosition"].AsVector3();
localPart.OffsetPosition = updatedPart.OffsetPosition; localPart.OffsetPosition = data["OffsetPosition"].AsVector3();
localPart.Scale = updatedPart.Scale; localPart.Scale = data["Scale"].AsVector3();
localPart.Velocity = updatedPart.Velocity; localPart.Velocity = data["Velocity"].AsVector3();
localPart.AngularVelocity = updatedPart.AngularVelocity; localPart.AngularVelocity = data["AngularVelocity"].AsVector3();
localPart.RotationOffset = updatedPart.RotationOffset; localPart.RotationOffset = data["RotationOffset"].AsQuaternion();
//properties in Physics bucket whose update processors are in PhysicsActor
/*
"Position":
"Size":
"Force":
"RotationalVelocity":
"PA_Acceleration":
"Torque":
"Orientation":
"IsPhysical":
"Flying":
"Buoyancy":
* */
m_bucketSyncInfoList[bucketName].LastUpdateTimeStamp = updatedPart.BucketSyncInfoList[bucketName].LastUpdateTimeStamp; if (pa != null)
m_bucketSyncInfoList[bucketName].LastUpdateActorID = updatedPart.BucketSyncInfoList[bucketName].LastUpdateActorID; {
pa.Size = data["Size"].AsVector3();
pa.Position = data["Position"].AsVector3();
pa.Force = data["Force"].AsVector3();
// pa.Velocity = data["Velocity"].AsVector3();
pa.RotationalVelocity = data["RotationalVelocity"].AsVector3();
pa.Acceleration = data["PA_Acceleration"].AsVector3();
pa.Torque = data["Torque"].AsVector3();
pa.Orientation = data["Orientation"].AsQuaternion();
pa.IsPhysical = data["IsPhysical"].AsBoolean();
pa.Flying = data["Flying"].AsBoolean();
pa.Kinematic = data["Kinematic"].AsBoolean();
pa.Buoyancy = (float)data["Buoyancy"].AsReal();
pa.CollidingGround = data["CollidingGround"].AsBoolean();
pa.IsColliding = data["IsColliding"].AsBoolean();
}
m_bucketSyncInfoList[bucketName].LastUpdateTimeStamp = data["LastUpdateTimeStamp"].AsLong();
m_bucketSyncInfoList[bucketName].LastUpdateActorID = data["LastUpdateActorID"].AsString();
} }
@ -5696,18 +5712,10 @@ namespace OpenSim.Region.Framework.Scenes
/// <param name="updatedPart">A container of the updated properties. Only the values of the updated properties are set.</param> /// <param name="updatedPart">A container of the updated properties. Only the values of the updated properties are set.</param>
/// <param name="rBucketSyncInfo">A copy of the sync info of the bucket on the sender's (who sends out the syn message) side.</param> /// <param name="rBucketSyncInfo">A copy of the sync info of the bucket on the sender's (who sends out the syn message) side.</param>
/// <returns></returns> /// <returns></returns>
public Scene.ObjectUpdateResult UpdateBucketProperties(string bucketName, SceneObjectPart updatedPart) public Scene.ObjectUpdateResult UpdateBucketProperties(string bucketName, Object updatedPart, BucketSyncInfo rBucketSyncInfo)
{ {
Scene.ObjectUpdateResult partUpdateResult = Scene.ObjectUpdateResult.Unchanged; Scene.ObjectUpdateResult partUpdateResult = Scene.ObjectUpdateResult.Unchanged;
if (!updatedPart.BucketSyncInfoList.ContainsKey(bucketName))
{
m_log.Warn("No bucket named " + bucketName + " found in the copy of updatedPart in UpdateBucketProperties");
return partUpdateResult;
}
BucketSyncInfo rBucketSyncInfo = updatedPart.BucketSyncInfoList[bucketName];
if (!m_bucketSyncInfoList.ContainsKey(bucketName)) if (!m_bucketSyncInfoList.ContainsKey(bucketName))
{ {
m_log.Error("SceneObjectPart.UpdateBucketProperties: no bucket name " + bucketName + " defined"); m_log.Error("SceneObjectPart.UpdateBucketProperties: no bucket name " + bucketName + " defined");

View File

@ -199,8 +199,8 @@ namespace OpenSim.Region.Physics.Manager
get { return m_UUID; } get { return m_UUID; }
} }
public PhysActorLastValues lastValues; public PhysActorLastValues lastValues;
// ID of actor which last updated the values. Send if I did the change. // set to true of prim is updated
public string ChangingActorID = "YY"; public bool SyncUpdated;
public abstract bool Grabbed { set; } public abstract bool Grabbed { set; }
@ -217,7 +217,7 @@ namespace OpenSim.Region.Physics.Manager
public abstract void LockAngularMotion(Vector3 axis); public abstract void LockAngularMotion(Vector3 axis);
public virtual void RequestPhysicsterseUpdate() public void RequestPhysicsterseUpdate()
{ {
// Make a temporary copy of the event to avoid possibility of // Make a temporary copy of the event to avoid possibility of
// a race condition if the last subscriber unsubscribes // a race condition if the last subscriber unsubscribes

View File

@ -203,23 +203,6 @@ namespace OpenSim.Region.Physics.OdePlugin
m_name = avName; m_name = avName;
} }
public override void RequestPhysicsterseUpdate()
{
if (PhysEngineToSceneConnectorModule.IsPhysEngineActorS)
{
// m_log.DebugFormat("[ODE CHARACTER]: Sending terse update for {0}", LocalID);
// if the values have changed and it was I who changed them, send an update
if (this.lastValues.Changed(this) && ChangingActorID == RegionSyncServerModule.ActorID)
{
PhysEngineToSceneConnectorModule.RouteUpdate(this);
}
}
else
{
base.RequestPhysicsterseUpdate();
}
}
public override int PhysicsActorType public override int PhysicsActorType
{ {
get { return (int) ActorTypes.Agent; } get { return (int) ActorTypes.Agent; }
@ -427,7 +410,6 @@ namespace OpenSim.Region.Physics.OdePlugin
get { return _position; } get { return _position; }
set set
{ {
base.ChangingActorID = RegionSyncServerModule.ActorID;
if (Body == IntPtr.Zero || Shell == IntPtr.Zero) if (Body == IntPtr.Zero || Shell == IntPtr.Zero)
{ {
if (value.IsFinite()) if (value.IsFinite())
@ -473,7 +455,6 @@ namespace OpenSim.Region.Physics.OdePlugin
get { return new Vector3(CAPSULE_RADIUS * 2, CAPSULE_RADIUS * 2, CAPSULE_LENGTH); } get { return new Vector3(CAPSULE_RADIUS * 2, CAPSULE_RADIUS * 2, CAPSULE_LENGTH); }
set set
{ {
base.ChangingActorID = RegionSyncServerModule.ActorID;
if (value.IsFinite()) if (value.IsFinite())
{ {
m_pidControllerActive = true; m_pidControllerActive = true;
@ -795,7 +776,6 @@ namespace OpenSim.Region.Physics.OdePlugin
{ {
m_pidControllerActive = true; m_pidControllerActive = true;
_target_velocity = value; _target_velocity = value;
base.ChangingActorID = RegionSyncServerModule.ActorID;
} }
else else
{ {
@ -853,7 +833,6 @@ namespace OpenSim.Region.Physics.OdePlugin
{ {
if (force.IsFinite()) if (force.IsFinite())
{ {
base.ChangingActorID = RegionSyncServerModule.ActorID;
if (pushforce) if (pushforce)
{ {
m_pidControllerActive = false; m_pidControllerActive = false;

View File

@ -257,21 +257,6 @@ namespace OpenSim.Region.Physics.OdePlugin
// primName, mesh == null ? "NULL" : "DEFINED", pbs == null ? "NULL" : "DEFINED", pisPhysical); // primName, mesh == null ? "NULL" : "DEFINED", pbs == null ? "NULL" : "DEFINED", pisPhysical);
} }
public override void RequestPhysicsterseUpdate()
{
if (PhysEngineToSceneConnectorModule.IsPhysEngineActorS)
{
// if the values have changed and it was I who changed them, send an update
// if (this.lastValues.Changed(this) && ChangingActorID == RegionSyncServerModule.ActorID)
if (this.lastValues.Changed(this))
PhysEngineToSceneConnectorModule.RouteUpdate(this);
}
else
{
base.RequestPhysicsterseUpdate();
}
}
public override int PhysicsActorType public override int PhysicsActorType
{ {
get { return (int) ActorTypes.Prim; } get { return (int) ActorTypes.Prim; }
@ -2300,7 +2285,6 @@ Console.WriteLine(" JointCreateFixed");
get { return _position; } get { return _position; }
set { _position = value; set { _position = value;
base.ChangingActorID = RegionSyncServerModule.ActorID;
//m_log.Info("[PHYSICS]: " + _position.ToString()); //m_log.Info("[PHYSICS]: " + _position.ToString());
} }
} }
@ -2313,7 +2297,6 @@ Console.WriteLine(" JointCreateFixed");
if (value.IsFinite()) if (value.IsFinite())
{ {
_size = value; _size = value;
base.ChangingActorID = RegionSyncServerModule.ActorID;
} }
else else
{ {
@ -2336,7 +2319,6 @@ Console.WriteLine(" JointCreateFixed");
if (value.IsFinite()) if (value.IsFinite())
{ {
m_force = value; m_force = value;
base.ChangingActorID = RegionSyncServerModule.ActorID;
} }
else else
{ {
@ -2395,7 +2377,6 @@ Console.WriteLine(" JointCreateFixed");
{ {
_pbs = value; _pbs = value;
m_taintshape = true; m_taintshape = true;
base.ChangingActorID = RegionSyncServerModule.ActorID;
} }
} }
@ -2418,7 +2399,6 @@ Console.WriteLine(" JointCreateFixed");
{ {
if (value.IsFinite()) if (value.IsFinite())
{ {
base.ChangingActorID = RegionSyncServerModule.ActorID;
_velocity = value; _velocity = value;
m_taintVelocity = value; m_taintVelocity = value;
@ -2448,7 +2428,6 @@ Console.WriteLine(" JointCreateFixed");
{ {
m_taintTorque = value; m_taintTorque = value;
_parent_scene.AddPhysicsActorTaint(this); _parent_scene.AddPhysicsActorTaint(this);
base.ChangingActorID = RegionSyncServerModule.ActorID;
} }
else else
{ {
@ -2477,7 +2456,6 @@ Console.WriteLine(" JointCreateFixed");
if (QuaternionIsFinite(value)) if (QuaternionIsFinite(value))
{ {
_orientation = value; _orientation = value;
base.ChangingActorID = RegionSyncServerModule.ActorID;
} }
else else
m_log.WarnFormat("[PHYSICS]: Got NaN quaternion Orientation from Scene in Object {0}", Name); m_log.WarnFormat("[PHYSICS]: Got NaN quaternion Orientation from Scene in Object {0}", Name);

View File

@ -91,19 +91,19 @@ public sealed class PEPrim : PhysicsActor
get { return _size; } get { return _size; }
set { _size = value; set { _size = value;
// m_log.Debug("[REMOTE PRIM ENGINE] PEPrim set Size"); // m_log.Debug("[REMOTE PRIM ENGINE] PEPrim set Size");
ChangingActorID = RegionSyncServerModule.ActorID; // SyncUpdated = true;
} }
} }
public override PrimitiveBaseShape Shape { public override PrimitiveBaseShape Shape {
set { _pbs = value; set { _pbs = value;
m_log.Debug("[REMOTE PRIM ENGINE] PEPrim set Shape"); m_log.Debug("[REMOTE PRIM ENGINE] PEPrim set Shape");
ChangingActorID = RegionSyncServerModule.ActorID; // SyncUpdated = true;
} }
} }
public override uint LocalID { public override uint LocalID {
set { _localID = value; set { _localID = value;
// m_log.Debug("[REMOTE PRIM ENGINE] PEPrim set LocalID"); // m_log.Debug("[REMOTE PRIM ENGINE] PEPrim set LocalID");
ChangingActorID = RegionSyncServerModule.ActorID; // SyncUpdated = true;
} }
get { return _localID; } get { return _localID; }
} }
@ -125,7 +125,7 @@ public sealed class PEPrim : PhysicsActor
public override Vector3 Position { public override Vector3 Position {
get { return _position; } get { return _position; }
set { _position = value; set { _position = value;
ChangingActorID = RegionSyncServerModule.ActorID; // SyncUpdated = true;
// m_log.Debug("[REMOTE PRIM ENGINE] PEPrim set Position"); // m_log.Debug("[REMOTE PRIM ENGINE] PEPrim set Position");
} }
} }
@ -135,7 +135,7 @@ public sealed class PEPrim : PhysicsActor
public override Vector3 Force { public override Vector3 Force {
get { return _force; } get { return _force; }
set { _force = value; set { _force = value;
ChangingActorID = RegionSyncServerModule.ActorID; // SyncUpdated = true;
// m_log.Debug("[REMOTE PRIM ENGINE] PEPrim set Force"); // m_log.Debug("[REMOTE PRIM ENGINE] PEPrim set Force");
} }
} }
@ -157,19 +157,19 @@ public sealed class PEPrim : PhysicsActor
public override Vector3 Velocity { public override Vector3 Velocity {
get { return _velocity; } get { return _velocity; }
set { _velocity = value; set { _velocity = value;
ChangingActorID = RegionSyncServerModule.ActorID; // SyncUpdated = true;
} }
} }
public override Vector3 Torque { public override Vector3 Torque {
get { return _torque; } get { return _torque; }
set { _torque = value; set { _torque = value;
ChangingActorID = RegionSyncServerModule.ActorID; // SyncUpdated = true;
} }
} }
public override float CollisionScore { public override float CollisionScore {
get { return _collisionScore; } get { return _collisionScore; }
set { _collisionScore = value; set { _collisionScore = value;
ChangingActorID = RegionSyncServerModule.ActorID; // SyncUpdated = true;
} }
} }
public override Vector3 Acceleration { public override Vector3 Acceleration {
@ -178,25 +178,25 @@ public sealed class PEPrim : PhysicsActor
public override Quaternion Orientation { public override Quaternion Orientation {
get { return _orientation; } get { return _orientation; }
set { _orientation = value; set { _orientation = value;
ChangingActorID = RegionSyncServerModule.ActorID; // SyncUpdated = true;
} }
} }
public override int PhysicsActorType { public override int PhysicsActorType {
get { return _physicsActorType; } get { return _physicsActorType; }
set { _physicsActorType = value; set { _physicsActorType = value;
ChangingActorID = RegionSyncServerModule.ActorID; // SyncUpdated = true;
} }
} }
public override bool IsPhysical { public override bool IsPhysical {
get { return _isPhysical; } get { return _isPhysical; }
set { _isPhysical = value; set { _isPhysical = value;
ChangingActorID = RegionSyncServerModule.ActorID; // SyncUpdated = true;
} }
} }
public override bool Flying { public override bool Flying {
get { return _flying; } get { return _flying; }
set { _flying = value; set { _flying = value;
ChangingActorID = RegionSyncServerModule.ActorID; // SyncUpdated = true;
} }
} }
public override bool public override bool

View File

@ -99,11 +99,6 @@ public class PEScene : PhysicsScene
public override void AddPhysicsActorTaint(PhysicsActor prim) { } public override void AddPhysicsActorTaint(PhysicsActor prim) { }
public override float Simulate(float timeStep) public override float Simulate(float timeStep)
{
// if we are a physics engine server, send update information
if (SceneToPhysEngineSyncServer.IsPhysEngineScene2S())
{
if (SceneToPhysEngineSyncServer.IsActivePhysEngineScene2S())
{ {
// m_log.DebugFormat("[RPE]: Simulate. p={0}, a={1}", m_prims.Count, m_avatars.Count); // m_log.DebugFormat("[RPE]: Simulate. p={0}, a={1}", m_prims.Count, m_avatars.Count);
lock (m_prims) lock (m_prims)
@ -111,9 +106,10 @@ public class PEScene : PhysicsScene
foreach (PEPrim prim in m_prims) foreach (PEPrim prim in m_prims)
{ {
// if the values have changed and it was I who changed them, send an update // if the values have changed and it was I who changed them, send an update
if (prim.ChangingActorID == RegionSyncServerModule.ActorID && prim.lastValues.Changed(prim)) if (prim.SyncUpdated)
{ {
SceneToPhysEngineSyncServer.RouteUpdate(prim); prim.SyncUpdated = false;
prim.RequestPhysicsterseUpdate();
} }
} }
} }
@ -123,15 +119,12 @@ public class PEScene : PhysicsScene
{ {
// m_log.DebugFormat("[RPE]: Simulate. p={0}, a={1}", m_prims.Count, m_avatars.Count); // m_log.DebugFormat("[RPE]: Simulate. p={0}, a={1}", m_prims.Count, m_avatars.Count);
// if the values have changed and it was I who changed them, send an update // if the values have changed and it was I who changed them, send an update
if (actor.ChangingActorID == RegionSyncServerModule.ActorID && actor.lastValues.Changed(actor)) if (actor.SyncUpdated)
{ {
SceneToPhysEngineSyncServer.RouteUpdate(actor); actor.RequestPhysicsterseUpdate();
} }
} }
} }
}
return 60f;
}
/* /*
// code borrowed from BasicPhysics to do just avatar movement // code borrowed from BasicPhysics to do just avatar movement
foreach (PECharacter actor in m_avatars) foreach (PECharacter actor in m_avatars)