From 9b34d506437cceb1c7f28e48221a33f72449aafd Mon Sep 17 00:00:00 2001 From: "Huaiyu (Kitty) Liu" Date: Wed, 5 Jan 2011 13:46:48 -0800 Subject: [PATCH] Tried a temporary solution for propogating events across actors. See OnUpdateScript handlers. --- .../SymmetricSync/RegionSyncModule.cs | 128 +++++++++++++++++- .../SymmetricSync/ScriptEngineSyncModule.cs | 14 +- .../SymmetricSync/SymmetricSyncMessage.cs | 7 +- .../Region/Framework/Scenes/EventManager.cs | 25 +++- .../Framework/Scenes/Scene.Inventory.cs | 61 ++++++++- 5 files changed, 223 insertions(+), 12 deletions(-) diff --git a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs index 586fdf16a5..4d675512af 100755 --- a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs +++ b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs @@ -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,12 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole; InstallInterfaces(); - //Register for the OnPostSceneCreation event + //Register for Scene events m_scene.EventManager.OnPostSceneCreation += OnPostSceneCreation; m_scene.EventManager.OnObjectBeingRemovedFromScene += new EventManager.ObjectBeingRemovedFromScene(RegionSyncModule_OnObjectBeingRemovedFromScene); + + //Register for scene events that need to be propogated to other actors + m_scene.EventManager.OnUpdateScript += RegionSyncModule_OnUpdateScript; } //Called after AddRegion() has been called for all region modules of the scene @@ -393,7 +397,10 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule //the actor operates on. private HashSet m_syncConnectors= new HashSet(); 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 +421,16 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule } } + private void SendSceneEventToRelevantSyncConnectors(string init_actorID, SymmetricSyncMessage rsm) + { + List syncConnectors = GetSyncConnectorsForSceneEvents(init_actorID, rsm); + + foreach (SyncConnector connector in syncConnectors) + { + connector.Send(rsm); + } + } + /// /// Check if we need to send out an update message for the given object. /// @@ -465,6 +482,39 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule return syncConnectors; } + /// + /// Get the set of SyncConnectors to send certain scene events. + /// + /// + /// + private List GetSyncConnectorsForSceneEvents(string init_actorID, SymmetricSyncMessage rsm) + { + List syncConnectors = new List(); + 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. @@ -774,7 +824,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule string sogxml = SceneObjectSerializer.ToXml2Format((SceneObjectGroup)e); SendSyncMessage(SymmetricSyncMessage.MsgType.NewObject, sogxml); - m_log.Debug(LogHeader + ": " + sogxml); + //m_log.Debug(LogHeader + ": " + sogxml); } } return; @@ -791,6 +841,12 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule HandleRemovedObject(msg); return; } + //EVENTS PROCESSING + case SymmetricSyncMessage.MsgType.OnUpdateScript: + { + HandleEvent_OnUpdateScript(msg); + return; + } default: return; } @@ -920,6 +976,36 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule } } + /// + /// Handler for SymmetricSyncMessage.MsgType.OnUpdateScript + /// + /// + private void HandleEvent_OnUpdateScript(SymmetricSyncMessage msg) + { + m_log.Debug(LogHeader + ", " + m_actorID + ": received OnUpdateScript"); + + OSDMap data = DeserializeMessage(msg); + + //get the event parameters, trigger the event in the local scene + string init_actorID = data["actorID"].AsString(); + 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(); + //m_scene.EventManager.TriggerUpdateScript(agentID, itemID, primID, isRunning, assetID); + + //trigger the OnUpdateScriptBySync event, so that the handler of the event knows it is event initiated remotely + m_scene.EventManager.TriggerOnUpdateScriptBySync(agentID, itemID, primID, isRunning, assetID); + + + //if this is a relay node, forwards the event + if (m_isSyncRelay) + { + SendSceneEventToRelevantSyncConnectors(init_actorID, msg); + } + } + /// /// Send a sync message to remove the given objects in all connected actors, if this is a relay node. @@ -945,6 +1031,42 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule } + /// + /// The handler for (locally initiated) event OnUpdateScript: publish it to other actors. + /// + /// + /// + /// + /// + /// + public void RegionSyncModule_OnUpdateScript(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); + + PublishSceneEvent(data); + } + + 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 } diff --git a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/ScriptEngineSyncModule.cs b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/ScriptEngineSyncModule.cs index 6c24792216..78471fb764 100755 --- a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/ScriptEngineSyncModule.cs +++ b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/ScriptEngineSyncModule.cs @@ -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 } - } \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/SymmetricSyncMessage.cs b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/SymmetricSyncMessage.cs index b4b960ace1..4785992374 100755 --- a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/SymmetricSyncMessage.cs +++ b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/SymmetricSyncMessage.cs @@ -25,17 +25,16 @@ 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 + OnUpdateScript, } #endregion diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index 7ba4f39d97..08f56cece9 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -38,6 +38,8 @@ 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 + /// /// A class for triggering remote scene events. /// @@ -2246,7 +2248,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; @@ -2291,6 +2292,28 @@ namespace OpenSim.Region.Framework.Scenes } } + public event UpdateScriptBySync OnUpdateScriptBySync; + public delegate void UpdateScriptBySync(UUID agentID, UUID itemId, UUID primId, bool isScriptRunning, UUID newAssetID); + public void TriggerOnUpdateScriptBySync(UUID agentID, UUID itemId, UUID primId, bool isScriptRunning, UUID newAssetID) + { + UpdateScriptBySync handlerUpdateScriptBySync = OnUpdateScriptBySync; + if (handlerUpdateScriptBySync != null) + { + foreach (UpdateScriptBySync d in handlerUpdateScriptBySync.GetInvocationList()) + { + try + { + d(agentID, itemId, primId, isScriptRunning, newAssetID); + } + catch (Exception e) + { + m_log.ErrorFormat( + "[EVENT MANAGER]: Delegate for TriggerOnUpdateScriptBySync failed - continuing. {0} {1}", + e.Message, e.StackTrace); + } + } + } + } //end of SYMMETRIC SYNC } } diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 468d30e413..900b19ce2f 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -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 - /// + #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 + + + /// /// CapsUpdateTaskInventoryScriptAsset(IClientAPI, UUID, UUID, bool, byte[]) /// public ArrayList CapsUpdateTaskInventoryScriptAsset(UUID avatarId, UUID itemId,