merged in Kitty's code on propogating events and handling remote events

dsg
Huaiyu (Kitty) Liu 2011-01-06 10:44:21 -08:00
commit e4ab31e004
9 changed files with 374 additions and 21 deletions

View File

@ -391,7 +391,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
//when an object is deleted, this function (DeleteObject) could be triggered more than once. So we check
//if the object part is already removed is the scene (part==null)
m_log.Debug("Inform script engine about the deleted object");
//m_log.Debug("Inform script engine about the deleted object");
if(m_sceneToSESyncServer!=null)
m_sceneToSESyncServer.SendToSE(rsm, part.ParentGroup);
}
@ -572,7 +572,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
//when an object is deleted, this function (DeleteObject) could be triggered more than once. So we check
//if the object part is already removed is the scene (part==null)
m_log.Debug("Inform script engine about the deleted object");
//m_log.Debug("Inform script engine about the deleted object");
m_sceneToSESyncServer.SendToSE(rsm, part.ParentGroup);
}
}

View File

@ -63,6 +63,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
m_active = true;
LogHeader += "-" + m_actorID;
m_log.Warn("[REGION SYNC MODULE] Initialised for actor "+ m_actorID);
//The ActorType configuration will be read in and process by an ActorSyncModule, not here.
@ -86,9 +87,10 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole;
InstallInterfaces();
//Register for the OnPostSceneCreation event
//Register for local Scene events
m_scene.EventManager.OnPostSceneCreation += OnPostSceneCreation;
m_scene.EventManager.OnObjectBeingRemovedFromScene += new EventManager.ObjectBeingRemovedFromScene(RegionSyncModule_OnObjectBeingRemovedFromScene);
}
//Called after AddRegion() has been called for all region modules of the scene
@ -393,7 +395,10 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
//the actor operates on.
private HashSet<SyncConnector> m_syncConnectors= new HashSet<SyncConnector>();
private object m_syncConnectorsLock = new object();
//seq number for scene events that are sent out to other actors
private ulong m_eventSeq = 0;
//Timers for periodically status report has not been implemented yet.
private System.Timers.Timer m_statsTimer = new System.Timers.Timer(1000);
private void StatsTimerElapsed(object source, System.Timers.ElapsedEventArgs e)
@ -414,6 +419,16 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
}
}
private void SendSceneEventToRelevantSyncConnectors(string init_actorID, SymmetricSyncMessage rsm)
{
List<SyncConnector> syncConnectors = GetSyncConnectorsForSceneEvents(init_actorID, rsm);
foreach (SyncConnector connector in syncConnectors)
{
connector.Send(rsm);
}
}
/// <summary>
/// Check if we need to send out an update message for the given object.
/// </summary>
@ -465,6 +480,39 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
return syncConnectors;
}
/// <summary>
/// Get the set of SyncConnectors to send certain scene events.
/// </summary>
/// <param name="sog"></param>
/// <returns></returns>
private List<SyncConnector> GetSyncConnectorsForSceneEvents(string init_actorID, SymmetricSyncMessage rsm)
{
List<SyncConnector> syncConnectors = new List<SyncConnector>();
if (m_isSyncRelay)
{
//This is a relay node in the synchronization overlay, forward it to all connectors, except the one that sends in the event
ForEachSyncConnector(delegate(SyncConnector connector)
{
if (connector.OtherSideActorID != init_actorID)
{
syncConnectors.Add(connector);
}
});
}
else
{
//This is a end node in the synchronization overlay (e.g. a non ScenePersistence actor). Get the right set of synconnectors.
//For now, there is only one syncconnector that connects to ScenePersistence, due to the star topology.
//This may go more complex when an actor connects to several ScenePersistence actors.
ForEachSyncConnector(delegate(SyncConnector connector)
{
syncConnectors.Add(connector);
});
}
return syncConnectors;
}
//NOTE: We proably don't need to do this, and there might not be a need for OnPostSceneCreation event to let RegionSyncModule
// and ActorSyncModules to gain some access to each other. We'll keep it here for a while, until we are sure it's not
// needed.
@ -791,6 +839,13 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
HandleRemovedObject(msg);
return;
}
//EVENTS PROCESSING
case SymmetricSyncMessage.MsgType.UpdateScript:
case SymmetricSyncMessage.MsgType.ScriptReset:
{
HandleRemoteEvent(msg);
return;
}
default:
return;
}
@ -920,6 +975,72 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
}
}
/// <summary>
/// The common actions for handling remote events (event initiated at other actors and propogated here)
/// </summary>
/// <param name="msg"></param>
private void HandleRemoteEvent(SymmetricSyncMessage msg)
{
OSDMap data = DeserializeMessage(msg);
string init_actorID = data["actorID"].AsString();
ulong evSeqNum = data["seqNum"].AsULong();
switch (msg.Type)
{
case SymmetricSyncMessage.MsgType.UpdateScript:
HandleRemoteEvent_OnUpdateScript(init_actorID, evSeqNum, data);
break;
case SymmetricSyncMessage.MsgType.ScriptReset:
HandleRemoteEvent_OnScriptReset(init_actorID, evSeqNum, data);
break;
}
//if this is a relay node, forwards the event
if (m_isSyncRelay)
{
SendSceneEventToRelevantSyncConnectors(init_actorID, msg);
}
}
/// <summary>
/// Special actions for remote event UpdateScript
/// </summary>
/// <param name="data">OSDMap data of event args</param>
private void HandleRemoteEvent_OnUpdateScript(string actorID, ulong evSeqNum, OSDMap data)
{
m_log.Debug(LogHeader + ", " + m_actorID + ": received UpdateScript");
UUID agentID = data["agentID"].AsUUID();
UUID itemID = data["itemID"].AsUUID();
UUID primID = data["primID"].AsUUID();
bool isRunning = data["running"].AsBoolean();
UUID assetID = data["assetID"].AsUUID();
//trigger the event in the local scene
m_scene.EventManager.TriggerUpdateScriptLocally(agentID, itemID, primID, isRunning, assetID);
}
/// <summary>
/// Special actions for remote event UpdateScript
/// </summary>
/// <param name="data">OSDMap data of event args</param>
private void HandleRemoteEvent_OnScriptReset(string actorID, ulong evSeqNum, OSDMap data)
{
m_log.Debug(LogHeader + ", " + m_actorID + ": received ScriptReset");
UUID agentID = data["agentID"].AsUUID();
UUID itemID = data["itemID"].AsUUID();
UUID primID = data["primID"].AsUUID();
SceneObjectPart part = m_scene.GetSceneObjectPart(primID);
if (part == null || part.ParentGroup.IsDeleted)
{
m_log.Warn(LogHeader + " part " + primID + " not exist, all is deleted");
return;
}
m_scene.EventManager.TriggerScriptResetLocally(part.LocalId, itemID);
}
/// <summary>
/// Send a sync message to remove the given objects in all connected actors, if this is a relay node.
@ -945,6 +1066,97 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
}
public void PublishSceneEvent(EventManager.EventNames ev, Object[] evArgs)
{
switch (ev)
{
case EventManager.EventNames.UpdateScript:
if (evArgs.Length < 5)
{
m_log.Error(LogHeader + " not enough event args for UpdateScript");
return;
}
m_log.Debug(LogHeader + " PublishSceneEvent UpdateScript");
OnLocalUpdateScript((UUID)evArgs[0], (UUID)evArgs[1], (UUID)evArgs[2], (bool)evArgs[3], (UUID)evArgs[4]);
return;
case EventManager.EventNames.ScriptReset:
if (evArgs.Length < 2)
{
m_log.Error(LogHeader + " not enough event args for ScriptReset");
return;
}
OnLocalScriptReset((uint)evArgs[0], (UUID)evArgs[1]);
return;
default:
return;
}
}
/// <summary>
/// The handler for (locally initiated) event OnUpdateScript: publish it to other actors.
/// </summary>
/// <param name="agentID"></param>
/// <param name="itemId"></param>
/// <param name="primId"></param>
/// <param name="isScriptRunning"></param>
/// <param name="newAssetID"></param>
private void OnLocalUpdateScript(UUID agentID, UUID itemId, UUID primId, bool isScriptRunning, UUID newAssetID)
{
m_log.Debug(LogHeader + " RegionSyncModule_OnUpdateScript");
OSDMap data = new OSDMap();
data["agentID"] = OSD.FromUUID(agentID);
data["itemID"] = OSD.FromUUID(itemId);
data["primID"] = OSD.FromUUID(primId);
data["running"] = OSD.FromBoolean(isScriptRunning);
data["assetID"] = OSD.FromUUID(newAssetID);
data["actorID"] = OSD.FromString(m_actorID);
data["seqNum"] = OSD.FromULong(GetNextEventSeq());
SymmetricSyncMessage rsm = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.UpdateScript, OSDParser.SerializeJsonString(data));
//send to actors who are interested in the event
SendSceneEventToRelevantSyncConnectors(m_actorID, rsm);
}
private void OnLocalScriptReset(uint localID, UUID itemID)
{
//we will use the prim's UUID as the identifier, not the localID, to publish the event for the prim
SceneObjectPart part = m_scene.GetSceneObjectPart(localID);
OSDMap data = new OSDMap();
data["primID"] = OSD.FromUUID(part.UUID);
data["itemID"] = OSD.FromUUID(itemID);
SendSceneEvent(SymmetricSyncMessage.MsgType.ScriptReset, data);
}
private void SendSceneEvent(SymmetricSyncMessage.MsgType msgType, OSDMap data)
{
data["actorID"] = OSD.FromString(m_actorID);
data["seqNum"] = OSD.FromULong(GetNextEventSeq());
SymmetricSyncMessage rsm = new SymmetricSyncMessage(msgType, OSDParser.SerializeJsonString(data));
//send to actors who are interested in the event
SendSceneEventToRelevantSyncConnectors(m_actorID, rsm);
}
/*
private void PublishSceneEvent(OSDMap data)
{
data["actorID"] = OSD.FromString(m_actorID);
data["seqNum"] = OSD.FromULong(GetNextEventSeq());
SymmetricSyncMessage rsm = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.OnUpdateScript, OSDParser.SerializeJsonString(data));
SendSceneEventToRelevantSyncConnectors(m_actorID, rsm);
}
* */
private ulong GetNextEventSeq()
{
return m_eventSeq++;
}
#endregion //RegionSyncModule members and functions
}

View File

@ -59,6 +59,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
m_active = true;
LogHeader += "-" + m_actorID;
m_log.Warn(LogHeader + " Initialised");
}
@ -85,6 +86,11 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
//Register for Scene/SceneGraph events
m_scene.SceneGraph.OnObjectCreate += new ObjectCreateDelegate(ScriptEngine_OnObjectCreate);
m_scene.EventManager.OnSymmetricSyncStop += ScriptEngine_OnSymmetricSyncStop;
//for local OnUpdateScript, we'll handle it the same way as a remove OnUpdateScript.
//RegionSyncModule will capture a locally initiated OnUpdateScript event and publish it to other actors.
m_scene.EventManager.OnUpdateScript += ScriptEngine_OnUpdateScript;
//m_scene.EventManager.OnUpdateScriptBySync += ScriptEngine_OnUpdateScript;
}
//Called after AddRegion() has been called for all region modules of the scene.
@ -176,9 +182,15 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
m_scene.DeleteAllSceneObjects();
}
//Assumption, when this function is triggered, the new script asset has already been saved.
public void ScriptEngine_OnUpdateScript(UUID agentID, UUID itemID, UUID primID, bool isScriptRunning, UUID newAssetID)
{
m_log.Debug(LogHeader + " ScriptEngine_OnUpdateScript");
m_scene.SymSync_OnUpdateScript(agentID, itemID, primID, isScriptRunning, newAssetID);
}
#endregion //ScriptEngineSyncModule
}
}

View File

@ -25,17 +25,17 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
GetTerrain,
GetObjects,
// SIM -> CM
// SIM <-> CM
Terrain,
NewObject, // objects
UpdatedObject, // objects
RemovedObject, // objects
// BIDIR
//EchoRequest,
//EchoResponse,
RegionName,
//RegionStatus,
ActorID,
//events
UpdateScript,
ScriptReset,
}
#endregion

View File

@ -26,7 +26,7 @@
*/
//KittyL: Added to support running script engine actor
using System;
using System.Collections.Generic;
using OpenMetaverse;
@ -65,6 +65,9 @@ namespace OpenSim.Region.Framework.Interfaces
void SendTerrainUpdates(string lastUpdateActorID);
//void SendDeleteObject(SceneObjectGroup sog);
//For propogating scene events to other actors
void PublishSceneEvent(EventManager.EventNames ev, Object[] evArgs);
//TODO LIST:
//Special API for handling avatars
//void QueuePresenceForTerseUpdate(ScenePresence presence)

View File

@ -38,10 +38,74 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion;
namespace OpenSim.Region.Framework.Scenes
{
//SYMMETRIC SYNC: Rename the original EventManager as EventManagerBase, and implement a new EventManager that inherits from EventManagerBase
/// <summary>
/// A class for triggering remote scene events.
/// A wrapper class to implement handle event differently depending on if they are initiated locally or remotelly (i.e. by another actor)
/// </summary>
public class EventManager
public class EventManager: EventManagerBase
{
private Scene m_scene;
//the events that we'll handle specially in sym-sync
public enum EventNames
{
UpdateScript,
ScriptReset,
}
public EventManager(Scene scene)
{
m_scene = scene;
}
#region UpdateScript
public override void TriggerUpdateScript(UUID clientId, UUID itemId, UUID primId, bool isScriptRunning, UUID newAssetID)
{
//publish the event to other actors who are intersted in it
if (m_scene.RegionSyncModule != null)
{
Object[] eventArgs = new Object[5];
eventArgs[0] = (Object) clientId;
eventArgs[1] = (Object)itemId;
eventArgs[2] = (Object)primId;
eventArgs[3] = (Object)isScriptRunning;
eventArgs[4] = (Object)newAssetID;
m_scene.RegionSyncModule.PublishSceneEvent(EventNames.UpdateScript, eventArgs);
}
//trigger event locally, as the legacy code does
TriggerUpdateScriptLocally(clientId, itemId, primId, isScriptRunning, newAssetID);
}
public void TriggerUpdateScriptLocally(UUID clientId, UUID itemId, UUID primId, bool isScriptRunning, UUID newAssetID)
{
base.TriggerUpdateScript(clientId, itemId, primId, isScriptRunning, newAssetID);
}
#endregion //UpdateScript
#region ScriptReset
public virtual void TriggerScriptReset(uint localID, UUID itemID)
{
if (m_scene.RegionSyncModule != null)
{
Object[] eventArgs = new Object[2];
eventArgs[0] = (Object)localID;
eventArgs[1] = (Object)itemID;
m_scene.RegionSyncModule.PublishSceneEvent(EventNames.ScriptReset, eventArgs);
}
}
public virtual void TriggerScriptResetLocally(uint localID, UUID itemID)
{
base.TriggerScriptReset(localID, itemID);
}
#endregion //UpdateScript
}
/// <summary>
/// A class for triggering scene events.
/// </summary>
public class EventManagerBase
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@ -905,7 +969,8 @@ namespace OpenSim.Region.Framework.Scenes
}
}
public void TriggerScriptReset(uint localID, UUID itemID)
//public void TriggerScriptReset(uint localID, UUID itemID)
public virtual void TriggerScriptReset(uint localID, UUID itemID)
{
ScriptResetDelegate handlerScriptReset = OnScriptReset;
if (handlerScriptReset != null)
@ -2193,7 +2258,7 @@ namespace OpenSim.Region.Framework.Scenes
//OnUpdateTaskInventoryScriptAsset: triggered after Scene receives client's upload of updated script and stores it as asset
public delegate void UpdateScript(UUID clientID, UUID itemId, UUID primId, bool isScriptRunning, UUID newAssetID);
public event UpdateScript OnUpdateScript;
public void TriggerUpdateScript(UUID clientId, UUID itemId, UUID primId, bool isScriptRunning, UUID newAssetID)
public virtual void TriggerUpdateScript(UUID clientId, UUID itemId, UUID primId, bool isScriptRunning, UUID newAssetID)
{
UpdateScript handlerUpdateScript = OnUpdateScript;
if (handlerUpdateScript != null)
@ -2246,7 +2311,6 @@ namespace OpenSim.Region.Framework.Scenes
//SYMMETRIC SYNC
public event PostSceneCreation OnPostSceneCreation;
public delegate void PostSceneCreation(Scene createdScene);
public void TriggerOnPostSceneCreation(Scene createdScene)
{
PostSceneCreation handler = OnPostSceneCreation;

View File

@ -251,6 +251,8 @@ namespace OpenSim.Region.Framework.Scenes
AssetService.Store(asset);
//REGION SYNC: if RegionSyncEnabled, move script related operations to be after update inventory item
//SYMMETRIC SYNC: commenting out old REGION SYNC code, the RemoveScriptInstance would be handled by ScriptEngineSyncModule
/*
if (!RegionSyncEnabled)
{
if (isScriptRunning)
@ -258,6 +260,7 @@ namespace OpenSim.Region.Framework.Scenes
part.Inventory.RemoveScriptInstance(item.ItemID, false);
}
}
* */
// Update item with new asset
item.AssetID = asset.FullID;
@ -267,6 +270,8 @@ namespace OpenSim.Region.Framework.Scenes
part.GetProperties(remoteClient);
////REGION SYNC
//SYMMETRIC SYNC: commenting out old REGION SYNC code, the RemoveScriptInstance would be handled by ScriptEngineSyncModule
/*
if (!RegionSyncEnabled)
{
//Original OpenSim code below
@ -302,6 +307,18 @@ namespace OpenSim.Region.Framework.Scenes
return errors;
}
* */
//SYMMETRIC SYNC: Distributed Scene Graph implementation
m_log.Debug("Scene.Inventory: to call EventManager.TriggerUpdateTaskInventoryScriptAsset, agentID: " + remoteClient.AgentId);
//Trigger OnUpdateScript event.
EventManager.TriggerUpdateScript(remoteClient.AgentId, itemId, primId, isScriptRunning, item.AssetID);
//For now, we simple tell client that script saved while waiting for remote script engine to re-rez the script.
//Later will change the BaseHttpServer's code to return error list to client.
//remoteClient.SendAgentAlertMessage("Script saved", false);
ArrayList errors = new ArrayList();
return errors;
}
#region REGION SYNC
@ -314,8 +331,9 @@ namespace OpenSim.Region.Framework.Scenes
public ArrayList OnUpdateScript(UUID avatarID, UUID itemID, UUID primID, bool isScriptRunning, UUID newAssetID)
{
ArrayList errors = new ArrayList();
//This function is supposed to be executed only on a remote script engine, not an authorative Scene
if (!IsSyncedScriptEngine())
//In the old async model, this function is supposed to be executed only on a remote script engine, not an authorative Scene
if (RegionSyncModule==null && !IsSyncedScriptEngine())
{
m_log.Warn("This is not the script engine. Should not have received OnUpdateScript event.");
return errors;
@ -350,7 +368,44 @@ namespace OpenSim.Region.Framework.Scenes
}
#endregion
/// <summary>
#region SYMMETRIC SYNC
//only a script engine actor is supposed to call this function
public ArrayList SymSync_OnUpdateScript(UUID avatarID, UUID itemID, UUID primID, bool isScriptRunning, UUID newAssetID)
{
ArrayList errors = new ArrayList();
SceneObjectPart part = GetSceneObjectPart(primID);
SceneObjectGroup group = part.ParentGroup;
if (isScriptRunning)
{
m_log.Debug("To RemoveScriptInstance");
part.Inventory.RemoveScriptInstance(itemID, false);
}
// Retrieve item
TaskInventoryItem item = group.GetInventoryItem(part.LocalId, itemID);
// Update item with new asset
item.AssetID = newAssetID;
group.UpdateInventoryItem(item);
m_log.Debug("UpdateInventoryItem on object "+group.UUID);
if (isScriptRunning)
{
// Needs to determine which engine was running it and use that
m_log.Debug("To CreateScriptInstance");
part.Inventory.CreateScriptInstance(itemID, 0, false, DefaultScriptEngine, 0);
errors = part.Inventory.GetScriptErrors(itemID);
}
part.ParentGroup.ResumeScripts();
return errors;
}
#endregion //SYMMETRIC SYNC
/// <summary>
/// <see>CapsUpdateTaskInventoryScriptAsset(IClientAPI, UUID, UUID, bool, byte[])</see>
/// </summary>
public ArrayList CapsUpdateTaskInventoryScriptAsset(UUID avatarId, UUID itemId,

View File

@ -821,7 +821,10 @@ namespace OpenSim.Region.Framework.Scenes
m_physicalPrim = physicalPrim;
m_seeIntoRegionFromNeighbor = SeeIntoRegionFromNeighbor;
m_eventManager = new EventManager();
//SYMMETRIC SYNC: pass Scene reference to EventManager
//m_eventManager = new EventManager();
m_eventManager = new EventManager(this);
//end of SYMMETRIC SYNC
m_permissions = new ScenePermissions(this);
m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this);
@ -1029,7 +1032,11 @@ namespace OpenSim.Region.Framework.Scenes
BordersLocked = false;
m_regInfo = regInfo;
m_eventManager = new EventManager();
//SYMMETRIC SYNC: pass Scene reference to EventManager
//m_eventManager = new EventManager();
m_eventManager = new EventManager(this);
//end of SYMMETRIC SYNC
m_lastUpdate = Util.EnvironmentTickCount();
}

View File

@ -217,7 +217,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
//SYMMETRIC SYNC
//KittyL: 12/27/2010, added ActorID for symmetric synch model
part.SetLastUpdateActorID();
//part.SetLastUpdateActorID();
// SceneObjectGroup.AddPart() tries to be smart and automatically set the LinkNum.
// We override that here