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
0.6.0-stable
Melanie Thielker 2008-09-07 22:01:25 +00:00
parent e3338bac20
commit 669f553400
3 changed files with 52 additions and 9 deletions

View File

@ -73,6 +73,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
private string m_CurrentEvent = String.Empty; private string m_CurrentEvent = String.Empty;
private bool m_InSelfDelete = false; private bool m_InSelfDelete = false;
private int m_MaxScriptQueue; private int m_MaxScriptQueue;
private bool m_SaveState = true;
private Dictionary<string,IScriptApi> m_Apis = new Dictionary<string,IScriptApi>(); private Dictionary<string,IScriptApi> m_Apis = new Dictionary<string,IScriptApi>();
@ -213,6 +214,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
return; return;
} }
m_SaveState = true;
string savedState = Path.Combine(Path.GetDirectoryName(assembly), string savedState = Path.Combine(Path.GetDirectoryName(assembly),
m_ItemID.ToString() + ".state"); m_ItemID.ToString() + ".state");
if (File.Exists(savedState)) if (File.Exists(savedState))
@ -257,6 +260,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
// we get new rez events on sim restart, too // we get new rez events on sim restart, too
// but if there is state, then we fire the change // but if there is state, then we fire the change
// event // event
// We loaded state, don't force a re-save
m_SaveState = false;
if (stateSource == StateSource.NewRez) if (stateSource == StateSource.NewRez)
{ {
// m_Engine.Log.Debug("[Script] Posted changed(CHANGED_REGION_RESTART) to script"); // 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_InEvent = false;
m_CurrentEvent = String.Empty; 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) catch (Exception e)
{ {
@ -589,6 +607,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
m_State = "default"; m_State = "default";
if (running) if (running)
Start(); Start();
m_SaveState = true;
PostEvent(new EventParams("state_entry", PostEvent(new EventParams("state_entry",
new Object[0], new DetectParams[0])); new Object[0], new DetectParams[0]));
} }
@ -607,6 +626,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
async.RemoveScript(m_LocalID, m_ItemID); async.RemoveScript(m_LocalID, m_ItemID);
if (m_CurrentEvent != "state_entry") if (m_CurrentEvent != "state_entry")
{ {
m_SaveState = true;
PostEvent(new EventParams("state_entry", PostEvent(new EventParams("state_entry",
new Object[0], new DetectParams[0])); new Object[0], new DetectParams[0]));
} }
@ -640,6 +660,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
public void SaveState(string assembly) 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; AsyncCommandManager async = (AsyncCommandManager)m_Engine.AsyncCommands;
PluginData = async.GetSerializationData(m_ItemID); PluginData = async.GetSerializationData(m_ItemID);

View File

@ -56,9 +56,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
{ {
bool running = instance.Running; bool running = instance.Running;
if (running)
instance.Stop(50);
XmlDocument xmldoc = new XmlDocument(); XmlDocument xmldoc = new XmlDocument();
XmlNode xmlnode = xmldoc.CreateNode(XmlNodeType.XmlDeclaration, XmlNode xmlnode = xmldoc.CreateNode(XmlNodeType.XmlDeclaration,
@ -182,9 +179,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
rootElement.AppendChild(plugins); rootElement.AppendChild(plugins);
if (running)
instance.Start();
return xmldoc.InnerXml; return xmldoc.InnerXml;
} }

View File

@ -210,6 +210,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
m_Scene.EventManager.OnScriptReset += OnScriptReset; m_Scene.EventManager.OnScriptReset += OnScriptReset;
m_Scene.EventManager.OnStartScript += OnStartScript; m_Scene.EventManager.OnStartScript += OnStartScript;
m_Scene.EventManager.OnStopScript += OnStopScript; m_Scene.EventManager.OnStopScript += OnStopScript;
m_Scene.EventManager.OnShutdown += OnShutdown;
m_AsyncCommands = new AsyncCommandManager(this); m_AsyncCommands = new AsyncCommandManager(this);
@ -247,6 +248,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
Object[] p = (Object[])o; Object[] p = (Object[])o;
int saveTime = (int)p[0]; int saveTime = (int)p[0];
if (saveTime > 0)
System.Threading.Thread.Sleep(saveTime); System.Threading.Thread.Sleep(saveTime);
// m_log.Debug("[XEngine] Backing up script states"); // m_log.Debug("[XEngine] Backing up script states");
@ -275,6 +277,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
instances.Clear(); instances.Clear();
if (saveTime > 0)
m_ThreadPool.QueueWorkItem(new WorkItemCallback(this.DoBackup), m_ThreadPool.QueueWorkItem(new WorkItemCallback(this.DoBackup),
new Object[] { saveTime }); new Object[] { saveTime });
@ -840,5 +843,23 @@ namespace OpenSim.Region.ScriptEngine.XEngine
{ {
return GetScriptState(itemID); return GetScriptState(itemID);
} }
public void OnShutdown()
{
List<IScriptInstance> instances = new List<IScriptInstance>();
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});
}
} }
} }