123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460 |
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Reflection;
- using OpenMetaverse;
- using OpenSim.Region.ScriptEngine.Shared;
- using log4net;
- namespace OpenSim.Region.ScriptEngine.DotNetEngine
- {
-
-
-
-
- [Serializable]
- public class EventQueueManager
- {
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
- public ScriptEngine m_ScriptEngine;
-
-
-
-
- internal static List<EventQueueThreadClass> eventQueueThreads = new List<EventQueueThreadClass>();
-
-
-
-
-
-
-
-
-
-
-
-
- public static int ThreadsToExit;
- public static object ThreadsToExitLock = new object();
-
-
-
-
- internal static int numberOfThreads;
- internal static int EventExecutionMaxQueueSize;
-
-
-
- private static int maxFunctionExecutionTimems
- {
- get { return (int)(maxFunctionExecutionTimens / 10000); }
- set { maxFunctionExecutionTimens = value * 10000; }
- }
-
-
-
-
- public static long maxFunctionExecutionTimens;
-
-
-
-
- public static bool EnforceMaxExecutionTime;
-
-
-
-
- private static bool KillScriptOnMaxFunctionExecutionTime;
-
-
-
- private List<uint> objectLocks = new List<uint>();
- private object tryLockLock = new object();
-
-
-
- public Queue<QueueItemStruct> eventQueue = new Queue<QueueItemStruct>();
- #region " Queue structures "
-
-
-
- public struct QueueItemStruct
- {
- public uint localID;
- public UUID itemID;
- public string functionName;
- public DetectParams[] llDetectParams;
- public object[] param;
- public Dictionary<KeyValuePair<int,int>,KeyValuePair<int,int>>
- LineMap;
- }
- #endregion
- #region " Initialization / Startup "
- public EventQueueManager(ScriptEngine _ScriptEngine)
- {
- m_ScriptEngine = _ScriptEngine;
- ReadConfig();
- AdjustNumberOfScriptThreads();
- }
- public void ReadConfig()
- {
-
- numberOfThreads = m_ScriptEngine.ScriptConfigSource.GetInt("NumberOfScriptThreads", 2);
- maxFunctionExecutionTimems = m_ScriptEngine.ScriptConfigSource.GetInt("MaxEventExecutionTimeMs", 5000);
- EnforceMaxExecutionTime = m_ScriptEngine.ScriptConfigSource.GetBoolean("EnforceMaxEventExecutionTime", true);
- KillScriptOnMaxFunctionExecutionTime = m_ScriptEngine.ScriptConfigSource.GetBoolean("DeactivateScriptOnTimeout", false);
- EventExecutionMaxQueueSize = m_ScriptEngine.ScriptConfigSource.GetInt("EventExecutionMaxQueueSize", 300);
-
- lock (eventQueueThreads)
- {
- foreach (EventQueueThreadClass EventQueueThread in eventQueueThreads)
- {
- EventQueueThread.ReadConfig();
- }
- }
- }
- #endregion
- #region " Shutdown all threads "
- ~EventQueueManager()
- {
- Stop();
- }
- private void Stop()
- {
- if (eventQueueThreads != null)
- {
-
- lock (eventQueueThreads)
- {
- foreach (EventQueueThreadClass EventQueueThread in new ArrayList(eventQueueThreads))
- {
- AbortThreadClass(EventQueueThread);
- }
-
-
- }
- }
-
- lock (eventQueue)
- {
- eventQueue.Clear();
- }
- }
- #endregion
- #region " Start / stop script execution threads (ThreadClasses) "
- private void StartNewThreadClass()
- {
- EventQueueThreadClass eqtc = new EventQueueThreadClass();
- eventQueueThreads.Add(eqtc);
-
- }
- private void AbortThreadClass(EventQueueThreadClass threadClass)
- {
- if (eventQueueThreads.Contains(threadClass))
- eventQueueThreads.Remove(threadClass);
- try
- {
- threadClass.Stop();
- }
- catch (Exception)
- {
-
-
- }
-
- }
- #endregion
- #region " Mutex locks for queue access "
-
-
-
-
-
- public bool TryLock(uint localID)
- {
- lock (tryLockLock)
- {
- if (objectLocks.Contains(localID) == true)
- {
- return false;
- }
- else
- {
- objectLocks.Add(localID);
- return true;
- }
- }
- }
-
-
-
-
- public void ReleaseLock(uint localID)
- {
- lock (tryLockLock)
- {
- if (objectLocks.Contains(localID) == true)
- {
- objectLocks.Remove(localID);
- }
- }
- }
- #endregion
-
- #region " Check execution queue for a specified Event"
-
-
-
-
-
-
-
- public bool CheckEeventQueueForEvent(uint localID, string FunctionName)
- {
- if (eventQueue.Count > 0)
- {
- lock (eventQueue)
- {
- foreach (EventQueueManager.QueueItemStruct QIS in eventQueue)
- {
- if ((QIS.functionName == FunctionName) && (QIS.localID == localID))
- return true;
- }
- }
- }
- return false;
- }
- #endregion
- #region " Add events to execution queue "
-
-
-
-
-
-
- public bool AddToObjectQueue(uint localID, string FunctionName, DetectParams[] qParams, params object[] param)
- {
-
-
-
- if (m_ScriptEngine.m_ScriptManager.Scripts.ContainsKey(localID) == false)
- {
-
- return false;
- }
- List<UUID> scriptKeys =
- m_ScriptEngine.m_ScriptManager.GetScriptKeys(localID);
- foreach (UUID itemID in scriptKeys)
- {
-
-
- AddToScriptQueue(localID, itemID, FunctionName, qParams, param);
- }
- return true;
- }
-
-
-
-
-
-
-
- public bool AddToScriptQueue(uint localID, UUID itemID, string FunctionName, DetectParams[] qParams, params object[] param)
- {
- List<UUID> keylist = m_ScriptEngine.m_ScriptManager.GetScriptKeys(localID);
- if (!keylist.Contains(itemID))
- {
- return false;
- }
- lock (eventQueue)
- {
- if (eventQueue.Count >= EventExecutionMaxQueueSize)
- {
- m_log.Error("[" + m_ScriptEngine.ScriptEngineName + "]: ERROR: Event execution queue item count is at " + eventQueue.Count + ". Config variable \"EventExecutionMaxQueueSize\" is set to " + EventExecutionMaxQueueSize + ", so ignoring new event.");
- m_log.Error("[" + m_ScriptEngine.ScriptEngineName + "]: Event ignored: localID: " + localID + ", itemID: " + itemID + ", FunctionName: " + FunctionName);
- return false;
- }
- InstanceData id = m_ScriptEngine.m_ScriptManager.GetScript(
- localID, itemID);
-
- QueueItemStruct QIS = new QueueItemStruct();
- QIS.localID = localID;
- QIS.itemID = itemID;
- QIS.functionName = FunctionName;
- QIS.llDetectParams = qParams;
- QIS.param = param;
- if (id != null)
- QIS.LineMap = id.LineMap;
-
- eventQueue.Enqueue(QIS);
- }
- return true;
- }
- #endregion
- #region " Maintenance thread "
-
-
-
-
- public void AdjustNumberOfScriptThreads()
- {
-
- if (eventQueueThreads.Count == numberOfThreads)
- return;
- lock (eventQueueThreads)
- {
- int diff = numberOfThreads - eventQueueThreads.Count;
-
-
- if (diff > 0)
- {
-
- for (int ThreadCount = eventQueueThreads.Count; ThreadCount < numberOfThreads; ThreadCount++)
- {
- StartNewThreadClass();
- }
- }
- if (diff < 0)
- {
-
- lock (ThreadsToExitLock)
- {
- ThreadsToExit = Math.Abs(diff);
- }
- }
- }
- }
-
-
-
- public void CheckScriptMaxExecTime()
- {
-
- lock (eventQueueThreads)
- {
- foreach (EventQueueThreadClass EventQueueThread in eventQueueThreads)
- {
-
- if (EventQueueThread.InExecution)
- {
-
- if (DateTime.Now.Ticks - EventQueueThread.LastExecutionStarted >
- maxFunctionExecutionTimens)
- {
-
-
- EventQueueThread.KillCurrentScript = KillScriptOnMaxFunctionExecutionTime;
-
- AbortThreadClass(EventQueueThread);
-
-
- }
- }
- }
- }
- }
- #endregion
-
-
-
-
-
-
-
-
-
- }
- }
|