From 669f55340005a450fc236db3b9d660878062219c Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sun, 7 Sep 2008 22:01:25 +0000 Subject: [PATCH] Xengine patch to force a persistence save on script creation. This prevents duplicate delivery of state_entry if a region is restarted just after saving the script. Changes script state saves to no longer abort long- running event handlers. Queues the save instead. Adds shutdown handler to save script state on irderly shutdown --- .../Shared/Instance/ScriptInstance.cs | 28 +++++++++++++++++++ .../Shared/Instance/ScriptSerializer.cs | 6 ---- .../Region/ScriptEngine/XEngine/XEngine.cs | 27 ++++++++++++++++-- 3 files changed, 52 insertions(+), 9 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs index d35bfa8056..08f9545c3c 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs @@ -73,6 +73,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance private string m_CurrentEvent = String.Empty; private bool m_InSelfDelete = false; private int m_MaxScriptQueue; + private bool m_SaveState = true; private Dictionary m_Apis = new Dictionary(); @@ -213,6 +214,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance return; } + m_SaveState = true; + string savedState = Path.Combine(Path.GetDirectoryName(assembly), m_ItemID.ToString() + ".state"); if (File.Exists(savedState)) @@ -257,6 +260,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance // we get new rez events on sim restart, too // but if there is state, then we fire the change // event + + // We loaded state, don't force a re-save + m_SaveState = false; + if (stateSource == StateSource.NewRez) { // m_Engine.Log.Debug("[Script] Posted changed(CHANGED_REGION_RESTART) to script"); @@ -487,6 +494,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance m_InEvent = false; m_CurrentEvent = String.Empty; + + if (m_SaveState) + { + // This will be the very first event we deliver + // (state_entry) in defualt state + // + + SaveState(m_Assembly); + + m_SaveState = false; + } } catch (Exception e) { @@ -589,6 +607,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance m_State = "default"; if (running) Start(); + m_SaveState = true; PostEvent(new EventParams("state_entry", new Object[0], new DetectParams[0])); } @@ -607,6 +626,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance async.RemoveScript(m_LocalID, m_ItemID); if (m_CurrentEvent != "state_entry") { + m_SaveState = true; PostEvent(new EventParams("state_entry", new Object[0], new DetectParams[0])); } @@ -640,6 +660,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance public void SaveState(string assembly) { + // If we're currently in an event, just tell it to save upon return + // + if(m_InEvent) + { + m_SaveState = true; + return; + } + AsyncCommandManager async = (AsyncCommandManager)m_Engine.AsyncCommands; PluginData = async.GetSerializationData(m_ItemID); diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptSerializer.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptSerializer.cs index bc9b1742d7..a794f02861 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptSerializer.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptSerializer.cs @@ -56,9 +56,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance { bool running = instance.Running; - if (running) - instance.Stop(50); - XmlDocument xmldoc = new XmlDocument(); XmlNode xmlnode = xmldoc.CreateNode(XmlNodeType.XmlDeclaration, @@ -182,9 +179,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance rootElement.AppendChild(plugins); - if (running) - instance.Start(); - return xmldoc.InnerXml; } diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index 485531d722..303e5e4ffc 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -210,6 +210,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine m_Scene.EventManager.OnScriptReset += OnScriptReset; m_Scene.EventManager.OnStartScript += OnStartScript; m_Scene.EventManager.OnStopScript += OnStopScript; + m_Scene.EventManager.OnShutdown += OnShutdown; m_AsyncCommands = new AsyncCommandManager(this); @@ -247,7 +248,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine Object[] p = (Object[])o; int saveTime = (int)p[0]; - System.Threading.Thread.Sleep(saveTime); + if (saveTime > 0) + System.Threading.Thread.Sleep(saveTime); // m_log.Debug("[XEngine] Backing up script states"); @@ -275,8 +277,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine instances.Clear(); - m_ThreadPool.QueueWorkItem(new WorkItemCallback(this.DoBackup), - new Object[] { saveTime }); + if (saveTime > 0) + m_ThreadPool.QueueWorkItem(new WorkItemCallback(this.DoBackup), + new Object[] { saveTime }); return 0; } @@ -840,5 +843,23 @@ namespace OpenSim.Region.ScriptEngine.XEngine { return GetScriptState(itemID); } + + public void OnShutdown() + { + List instances = new List(); + + lock (m_Scripts) + { + foreach (IScriptInstance instance in m_Scripts.Values) + instances.Add(instance); + } + + foreach (IScriptInstance i in instances) + { + i.Stop(50); + } + + DoBackup(new Object[] {0}); + } } }