From a2985b5655d336b6da3ae48dcf80b9cbb16b90fb Mon Sep 17 00:00:00 2001
From: Melanie Thielker
Date: Wed, 27 Aug 2008 21:36:03 +0000
Subject: Refactor Executor into the script app domain and IScript. This
changes an implicit reference into a proxied one and further reduces memory
consumption of XEngine
---
.../ScriptEngine/Shared/Api/Runtime/Executor.cs | 240 +++++++++++++++++++++
...nSim.Region.ScriptEngine.Shared.Api.Runtime.mdp | 1 +
.../ScriptEngine/Shared/Api/Runtime/ScriptBase.cs | 14 ++
3 files changed, 255 insertions(+)
create mode 100644 OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Executor.cs
(limited to 'OpenSim/Region/ScriptEngine/Shared/Api/Runtime')
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Executor.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Executor.cs
new file mode 100644
index 0000000..0241da5
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Executor.cs
@@ -0,0 +1,240 @@
+/*
+ * 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 OpenSim 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.Reflection;
+using System.Runtime.Remoting.Lifetime;
+using OpenSim.Region.ScriptEngine.Shared;
+using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
+
+namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
+{
+ public class Executor : MarshalByRefObject
+ {
+ ///
+ /// Contains the script to execute functions in.
+ ///
+ protected IScript m_Script;
+
+ protected Dictionary m_eventFlagsMap = new Dictionary();
+
+ [Flags]
+ public enum scriptEvents : int
+ {
+ None = 0,
+ attach = 1,
+ collision = 16,
+ collision_end = 32,
+ collision_start = 64,
+ control = 128,
+ dataserver = 256,
+ email = 512,
+ http_response = 1024,
+ land_collision = 2048,
+ land_collision_end = 4096,
+ land_collision_start = 8192,
+ at_target = 16384,
+ listen = 32768,
+ money = 65536,
+ moving_end = 131072,
+ moving_start = 262144,
+ not_at_rot_target = 524288,
+ not_at_target = 1048576,
+ remote_data = 8388608,
+ run_time_permissions = 268435456,
+ state_entry = 1073741824,
+ state_exit = 2,
+ timer = 4,
+ touch = 8,
+ touch_end = 536870912,
+ touch_start = 2097152,
+ object_rez = 4194304
+ }
+
+ // Cache functions by keeping a reference to them in a dictionary
+ private Dictionary Events = new Dictionary();
+ private Dictionary m_stateEvents = new Dictionary();
+
+ public Executor(IScript script)
+ {
+ m_Script = script;
+ initEventFlags();
+ }
+
+ ///
+ /// Make sure our object does not timeout when in AppDomain. (Called by ILease base class)
+ ///
+ ///
+ public Object InitializeLifetimeService()
+ {
+ //Console.WriteLine("Executor: InitializeLifetimeService()");
+ // return null;
+ ILease lease = (ILease)base.InitializeLifetimeService();
+
+ if (lease.CurrentState == LeaseState.Initial)
+ {
+ lease.InitialLeaseTime = TimeSpan.Zero; // TimeSpan.FromMinutes(1);
+ // lease.SponsorshipTimeout = TimeSpan.FromMinutes(2);
+ // lease.RenewOnCallTime = TimeSpan.FromSeconds(2);
+ }
+ return lease;
+ }
+
+
+ public scriptEvents GetStateEventFlags(string state)
+ {
+ //Console.WriteLine("Get event flags for " + state);
+
+ // Check to see if we've already computed the flags for this state
+ scriptEvents eventFlags = scriptEvents.None;
+ if (m_stateEvents.ContainsKey(state))
+ {
+ m_stateEvents.TryGetValue(state, out eventFlags);
+ return eventFlags;
+ }
+
+ Type type=m_Script.GetType();
+
+ // Fill in the events for this state, cache the results in the map
+ foreach (KeyValuePair kvp in m_eventFlagsMap)
+ {
+ string evname = state + "_event_" + kvp.Key;
+ //Console.WriteLine("Trying event "+evname);
+ try
+ {
+ MethodInfo mi = type.GetMethod(evname);
+ if (mi != null)
+ {
+ //Console.WriteLine("Found handler for " + kvp.Key);
+ eventFlags |= kvp.Value;
+ }
+ }
+ catch(Exception)
+ {
+ //Console.WriteLine("Exeption in GetMethod:\n"+e.ToString());
+ }
+ }
+
+ // Save the flags we just computed and return the result
+ if (eventFlags != 0)
+ m_stateEvents.Add(state, eventFlags);
+
+ //Console.WriteLine("Returning {0:x}", eventFlags);
+ return (eventFlags);
+ }
+
+ public void ExecuteEvent(string state, string FunctionName, object[] args)
+ {
+ // IMPORTANT: Types and MemberInfo-derived objects require a LOT of memory.
+ // Instead use RuntimeTypeHandle, RuntimeFieldHandle and RunTimeHandle (IntPtr) instead!
+
+ string EventName = state + "_event_" + FunctionName;
+
+//#if DEBUG
+// Console.WriteLine("ScriptEngine: Script event function name: " + EventName);
+//#endif
+
+ if (Events.ContainsKey(EventName) == false)
+ {
+ // Not found, create
+ Type type = m_Script.GetType();
+ try
+ {
+ MethodInfo mi = type.GetMethod(EventName);
+ Events.Add(EventName, mi);
+ }
+ catch
+ {
+ Console.WriteLine("Event {0}not found", EventName);
+ // Event name not found, cache it as not found
+ Events.Add(EventName, null);
+ }
+ }
+
+ // Get event
+ MethodInfo ev = null;
+ Events.TryGetValue(EventName, out ev);
+
+ if (ev == null) // No event by that name!
+ {
+ //Console.WriteLine("ScriptEngine Can not find any event named: \String.Empty + EventName + "\String.Empty);
+ return;
+ }
+
+//cfk 2-7-08 dont need this right now and the default Linux build has DEBUG defined
+#if DEBUG
+ //Console.WriteLine("ScriptEngine: Executing function name: " + EventName);
+#endif
+ // Found
+ ev.Invoke(m_Script, args);
+ }
+
+ protected void initEventFlags()
+ {
+ // Initialize the table if it hasn't already been done
+ if (m_eventFlagsMap.Count > 0)
+ {
+ return;
+ }
+
+ m_eventFlagsMap.Add("attach", scriptEvents.attach);
+ // m_eventFlagsMap.Add("at_rot_target",(long)scriptEvents.at_rot_target);
+ m_eventFlagsMap.Add("at_target", scriptEvents.at_target);
+ // m_eventFlagsMap.Add("changed",(long)scriptEvents.changed);
+ m_eventFlagsMap.Add("collision", scriptEvents.collision);
+ m_eventFlagsMap.Add("collision_end", scriptEvents.collision_end);
+ m_eventFlagsMap.Add("collision_start", scriptEvents.collision_start);
+ m_eventFlagsMap.Add("control", scriptEvents.control);
+ m_eventFlagsMap.Add("dataserver", scriptEvents.dataserver);
+ m_eventFlagsMap.Add("email", scriptEvents.email);
+ m_eventFlagsMap.Add("http_response", scriptEvents.http_response);
+ m_eventFlagsMap.Add("land_collision", scriptEvents.land_collision);
+ m_eventFlagsMap.Add("land_collision_end", scriptEvents.land_collision_end);
+ m_eventFlagsMap.Add("land_collision_start", scriptEvents.land_collision_start);
+ // m_eventFlagsMap.Add("link_message",scriptEvents.link_message);
+ m_eventFlagsMap.Add("listen", scriptEvents.listen);
+ m_eventFlagsMap.Add("money", scriptEvents.money);
+ m_eventFlagsMap.Add("moving_end", scriptEvents.moving_end);
+ m_eventFlagsMap.Add("moving_start", scriptEvents.moving_start);
+ m_eventFlagsMap.Add("not_at_rot_target", scriptEvents.not_at_rot_target);
+ m_eventFlagsMap.Add("not_at_target", scriptEvents.not_at_target);
+ // m_eventFlagsMap.Add("no_sensor",(long)scriptEvents.no_sensor);
+ // m_eventFlagsMap.Add("on_rez",(long)scriptEvents.on_rez);
+ m_eventFlagsMap.Add("remote_data", scriptEvents.remote_data);
+ m_eventFlagsMap.Add("run_time_permissions", scriptEvents.run_time_permissions);
+ // m_eventFlagsMap.Add("sensor",(long)scriptEvents.sensor);
+ m_eventFlagsMap.Add("state_entry", scriptEvents.state_entry);
+ m_eventFlagsMap.Add("state_exit", scriptEvents.state_exit);
+ m_eventFlagsMap.Add("timer", scriptEvents.timer);
+ m_eventFlagsMap.Add("touch", scriptEvents.touch);
+ m_eventFlagsMap.Add("touch_end", scriptEvents.touch_end);
+ m_eventFlagsMap.Add("touch_start", scriptEvents.touch_start);
+ m_eventFlagsMap.Add("object_rez", scriptEvents.object_rez);
+ }
+ }
+}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OpenSim.Region.ScriptEngine.Shared.Api.Runtime.mdp b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OpenSim.Region.ScriptEngine.Shared.Api.Runtime.mdp
index 37bedfc..87904bb 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OpenSim.Region.ScriptEngine.Shared.Api.Runtime.mdp
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OpenSim.Region.ScriptEngine.Shared.Api.Runtime.mdp
@@ -17,6 +17,7 @@
+
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/ScriptBase.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/ScriptBase.cs
index c28aa9a..9f0dd27 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/ScriptBase.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/ScriptBase.cs
@@ -56,6 +56,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
public ScriptBaseClass()
{
+ m_Executor = new Executor(this);
+
MethodInfo[] myArrayMethodInfo = GetType().GetMethods(BindingFlags.Public|BindingFlags.Instance);
foreach (MethodInfo mi in myArrayMethodInfo)
@@ -68,6 +70,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
}
}
+ private Executor m_Executor = null;
+
+ public int GetStateEventFlags(string state)
+ {
+ return (int)m_Executor.GetStateEventFlags(state);
+ }
+
+ public void ExecuteEvent(string state, string FunctionName, object[] args)
+ {
+ m_Executor.ExecuteEvent(state, FunctionName, args);
+ }
+
public string[] GetApis()
{
string[] apis = new string[inits.Count];
--
cgit v1.1