OpenSimMirror/OpenSim/ScriptEngine/Components/DotNetEngine/Scheduler/ScriptManager_ScriptLoadUnl...

287 lines
12 KiB
C#

/*
* 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 OpenSimulator 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.Globalization;
using System.Reflection;
using System.Text;
using System.Threading;
using log4net;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Region.Environment.Scenes;
using OpenSim.Region.ScriptEngine.Interfaces;
using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
using OpenSim.ScriptEngine.Shared;
namespace OpenSim.ScriptEngine.Components.DotNetEngine.Scheduler
{
public partial class ScriptManager
{
private Queue<LoadUnloadStructure> LUQueue = new Queue<LoadUnloadStructure>();
private int LoadUnloadMaxQueueSize = 500;
private Object scriptLock = new Object();
//private Dictionary<InstanceData, DetectParams[]> detparms = new Dictionary<InstanceData, DetectParams[]>();
// Load/Unload structure
public void AddScript(ScriptStructure script)
{
lock (LUQueue)
{
if ((LUQueue.Count >= LoadUnloadMaxQueueSize))
{
m_log.ErrorFormat("[{0}] ERROR: Load queue count is at {1} of max {2}. Ignoring load request for script LocalID: {3}, ItemID: {4}.",
Name, LUQueue.Count, LoadUnloadMaxQueueSize, script.LocalID, script.ItemID);
return;
}
LoadUnloadStructure ls = new LoadUnloadStructure();
ls.Script = script;
ls.Action = LoadUnloadStructure.LUType.Load;
LUQueue.Enqueue(ls);
}
}
public void RemoveScript(uint localID, UUID itemID)
{
LoadUnloadStructure ls = new LoadUnloadStructure();
// See if we can find script
if (!TryGetScript(localID, itemID, ref ls.Script))
{
// Set manually
ls.Script.LocalID = localID;
ls.Script.ItemID = itemID;
}
ls.Script.StartParam = 0;
ls.Action = LoadUnloadStructure.LUType.Unload;
ls.PostOnRez = false;
lock (LUQueue)
{
LUQueue.Enqueue(ls);
}
}
internal bool DoScriptLoadUnload()
{
bool ret = false;
// if (!m_started)
// return;
lock (LUQueue)
{
if (LUQueue.Count > 0)
{
LoadUnloadStructure item = LUQueue.Dequeue();
ret = true;
if (item.Action == LoadUnloadStructure.LUType.Unload)
{
m_log.DebugFormat("[{0}] Unloading script", Name);
_StopScript(item.Script.LocalID, item.Script.ItemID);
RemoveScript(item.Script.LocalID, item.Script.ItemID);
}
else if (item.Action == LoadUnloadStructure.LUType.Load)
{
m_log.DebugFormat("[{0}] Loading script", Name);
_StartScript(item);
}
}
}
return ret;
}
//public void _StartScript(uint localID, UUID itemID, string Script, int startParam, bool postOnRez)
private void _StartScript(LoadUnloadStructure ScriptObject)
{
m_log.DebugFormat(
"[{0}]: ScriptManager StartScript: localID: {1}, itemID: {2}",
Name, ScriptObject.Script.LocalID, ScriptObject.Script.ItemID);
// We will initialize and start the script.
// It will be up to the script itself to hook up the correct events.
SceneObjectPart m_host = ScriptObject.Script.RegionInfo.Scene.GetSceneObjectPart(ScriptObject.Script.LocalID);
if (null == m_host)
{
m_log.ErrorFormat(
"[{0}]: Could not find scene object part corresponding " +
"to localID {1} to start script",
Name, ScriptObject.Script.LocalID);
return;
}
UUID assetID = UUID.Zero;
TaskInventoryItem taskInventoryItem = new TaskInventoryItem();
if (m_host.TaskInventory.TryGetValue(ScriptObject.Script.ItemID, out taskInventoryItem))
assetID = taskInventoryItem.AssetID;
ScenePresence presence =
ScriptObject.Script.RegionInfo.Scene.GetScenePresence(taskInventoryItem.OwnerID);
CultureInfo USCulture = new CultureInfo("en-US");
Thread.CurrentThread.CurrentCulture = USCulture;
try
{
//
// Compile script to an assembly
//
//TODO: DEBUG
BaseClassFactory.MakeBaseClass(ScriptObject.Script);
m_log.DebugFormat("[{0}] Compiling script {1}", Name, ScriptObject.Script.Name);
string fileName = "";
try
{
IScriptCompiler compiler =
ScriptObject.Script.RegionInfo.FindCompiler(ScriptObject.Script.ScriptMetaData);
RegionInfoStructure currentRegionInfo = ScriptObject.Script.RegionInfo;
fileName = compiler.Compile(ScriptObject.Script.ScriptMetaData,
ref ScriptObject.Script.Source);
ScriptObject.Script.AssemblyFileName = fileName;
}
catch (Exception e)
{
m_log.ErrorFormat("[{0}] Internal error while compiling \"{1}\": {2}", Name, ScriptObject.Script.Name, e.ToString());
}
m_log.DebugFormat("[{0}] Compiled \"{1}\" to assembly: \"{2}\".", Name, ScriptObject.Script.Name, fileName);
// Add it to our script memstruct
MemAddScript(ScriptObject.Script);
ScriptAssemblies.IScript CompiledScript;
CompiledScript = CurrentRegion.ScriptLoader.LoadScript(ScriptObject.Script);
ScriptObject.Script.State = "default";
ScriptObject.Script.ScriptObject = CompiledScript;
ScriptObject.Script.Disabled = false;
ScriptObject.Script.Running = true;
//id.LineMap = LSLCompiler.LineMap();
//id.Script = CompiledScript;
//id.Source = item.Script.Script;
//item.StartParam = startParam;
// TODO: Fire the first start-event
//int eventFlags =
// m_scriptEngine.m_ScriptManager.GetStateEventFlags(
// localID, itemID);
//m_host.SetScriptEvents(itemID, eventFlags);
ScriptObject.Script.RegionInfo.Executors_Execute(ScriptObject.Script,
new EventParams(ScriptObject.Script.LocalID, ScriptObject.Script.ItemID, "state_entry", new object[] { }, new Region.ScriptEngine.Shared.DetectParams[0])
);
if (ScriptObject.PostOnRez)
{
ScriptObject.Script.RegionInfo.Executors_Execute(ScriptObject.Script,
new EventParams(ScriptObject.Script.LocalID, "on_rez", new object[]
{new Region.ScriptEngine.Shared.LSL_Types.LSLInteger(ScriptObject.StartParam)
}, new Region.ScriptEngine.Shared.DetectParams[0]));
}
}
catch (Exception e) // LEGIT: User Scripting
{
if (presence != null && (!ScriptObject.PostOnRez))
presence.ControllingClient.SendAgentAlertMessage(
"Script saved with errors, check debug window!",
false);
try
{
// DISPLAY ERROR INWORLD
string text = "Error compiling script:\n" +
e.Message.ToString();
if (text.Length > 1100)
text = text.Substring(0, 1099);
ScriptObject.Script.RegionInfo.Scene.SimChat(Utils.StringToBytes(text),
ChatTypeEnum.DebugChannel, 2147483647,
m_host.AbsolutePosition, m_host.Name, m_host.UUID,
false);
}
catch (Exception e2) // LEGIT: User Scripting
{
m_log.Error("[" +
Name +
"]: Error displaying error in-world: " +
e2.ToString());
m_log.Error("[" +
Name + "]: " +
"Errormessage: Error compiling script:\r\n" +
e2.Message.ToString());
}
}
}
public void _StopScript(uint localID, UUID itemID)
{
ScriptStructure ss = new ScriptStructure();
if (!TryGetScript(localID, itemID, ref ss))
return;
// Stop long command on script
//AsyncCommandManager.RemoveScript(ss);
try
{
// Get AppDomain
// Tell script not to accept new requests
ss.Running = false;
ss.Disabled = true;
AppDomain ad = ss.AppDomain;
// Remove from internal structure
MemRemoveScript(localID, itemID);
// TODO: Tell AppDomain that we have stopped script
}
catch (Exception e) // LEGIT: User Scripting
{
m_log.Error("[" +
Name +
"]: Exception stopping script localID: " +
localID + " LLUID: " + itemID.ToString() +
": " + e.ToString());
}
}
}
}