From a43bb10000ca0b58af2f33750ea17cb94bfbad7d Mon Sep 17 00:00:00 2001 From: Tedd Hansen Date: Fri, 22 Feb 2008 14:09:38 +0000 Subject: Execution threads are now shared between regions too. Default thread count regardless of number of regions is now 3. This will save you around 33 threads for a normal 3x3 region server. But, this is totally completely untested. So it probably won't work for another patch or five. --- .../ScriptEngineBase/EventQueueThreadClass.cs | 402 +++++++++++---------- 1 file changed, 209 insertions(+), 193 deletions(-) (limited to 'OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs') diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs index 11fd896..f36baa7 100644 --- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs +++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs @@ -40,27 +40,27 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase /// /// Because every thread needs some data set for it (time started to execute current function), it will do its work within a class /// - public class EventQueueThreadClass: iScriptEngineFunctionModule + public class EventQueueThreadClass : iScriptEngineFunctionModule { /// /// How many ms to sleep if queue is empty /// - private int nothingToDoSleepms;// = 50; - private ThreadPriority MyThreadPriority; + private static int nothingToDoSleepms;// = 50; + private static ThreadPriority MyThreadPriority; public long LastExecutionStarted; public bool InExecution = false; public bool KillCurrentScript = false; - private EventQueueManager eventQueueManager; + //private EventQueueManager eventQueueManager; public Thread EventQueueThread; private static int ThreadCount = 0; private string ScriptEngineName = "ScriptEngine.Common"; - public EventQueueThreadClass(EventQueueManager eqm) + public EventQueueThreadClass()//EventQueueManager eqm { - eventQueueManager = eqm; + //eventQueueManager = eqm; ReadConfig(); Start(); } @@ -72,32 +72,36 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase public void ReadConfig() { - ScriptEngineName = eventQueueManager.m_ScriptEngine.ScriptEngineName; - nothingToDoSleepms = eventQueueManager.m_ScriptEngine.ScriptConfigSource.GetInt("SleepTimeIfNoScriptExecutionMs", 50); - - // Later with ScriptServer we might want to ask OS for stuff too, so doing this a bit manually - string pri = eventQueueManager.m_ScriptEngine.ScriptConfigSource.GetString("ScriptThreadPriority", "BelowNormal"); - switch (pri.ToLower()) + foreach (ScriptEngine m_ScriptEngine in ScriptEngine.ScriptEngines) { - case "lowest": - MyThreadPriority = ThreadPriority.Lowest; - break; - case "belownormal": - MyThreadPriority = ThreadPriority.BelowNormal; - break; - case "normal": - MyThreadPriority = ThreadPriority.Normal; - break; - case "abovenormal": - MyThreadPriority = ThreadPriority.AboveNormal; - break; - case "highest": - MyThreadPriority = ThreadPriority.Highest; - break; - default: - MyThreadPriority = ThreadPriority.BelowNormal; // Default - eventQueueManager.m_ScriptEngine.Log.Error("[ScriptEngineBase]: Unknown priority type \"" + pri + "\" in config file. Defaulting to \"BelowNormal\"."); - break; + ScriptEngineName = m_ScriptEngine.ScriptEngineName; + nothingToDoSleepms = m_ScriptEngine.ScriptConfigSource.GetInt("SleepTimeIfNoScriptExecutionMs", 50); + + // Later with ScriptServer we might want to ask OS for stuff too, so doing this a bit manually + string pri = m_ScriptEngine.ScriptConfigSource.GetString("ScriptThreadPriority", "BelowNormal"); + switch (pri.ToLower()) + { + case "lowest": + MyThreadPriority = ThreadPriority.Lowest; + break; + case "belownormal": + MyThreadPriority = ThreadPriority.BelowNormal; + break; + case "normal": + MyThreadPriority = ThreadPriority.Normal; + break; + case "abovenormal": + MyThreadPriority = ThreadPriority.AboveNormal; + break; + case "highest": + MyThreadPriority = ThreadPriority.Highest; + break; + default: + MyThreadPriority = ThreadPriority.BelowNormal; // Default + m_ScriptEngine.Log.Error("[ScriptEngineBase]: Unknown priority type \"" + pri + + "\" in config file. Defaulting to \"BelowNormal\"."); + break; + } } // Now set that priority @@ -113,7 +117,7 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase { EventQueueThread = new Thread(EventQueueThreadLoop); EventQueueThread.IsBackground = true; - + EventQueueThread.Priority = MyThreadPriority; EventQueueThread.Name = "EventQueueManagerThread_" + ThreadCount; EventQueueThread.Start(); @@ -127,8 +131,8 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase public void Stop() { - PleaseShutdown = true; // Set shutdown flag - Thread.Sleep(100); // Wait a bit + //PleaseShutdown = true; // Set shutdown flag + //Thread.Sleep(100); // Wait a bit if (EventQueueThread != null && EventQueueThread.IsAlive == true) { try @@ -143,6 +147,8 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase } } + private EventQueueManager.QueueItemStruct BlankQIS = new EventQueueManager.QueueItemStruct(); + private ScriptEngine lastScriptEngine; /// /// Queue processing thread loop /// @@ -151,188 +157,198 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase //myScriptEngine.Log.Info("[" + ScriptEngineName + "]: EventQueueManager Worker thread spawned"); try { - while (true) + while (true) { try { - EventQueueManager.QueueItemStruct BlankQIS = new EventQueueManager.QueueItemStruct(); while (true) { - // Every now and then check if we should shut down - if (PleaseShutdown || eventQueueManager.ThreadsToExit > 0) - { - // Someone should shut down, lets get exclusive lock - lock (eventQueueManager.ThreadsToExitLock) - { - // Lets re-check in case someone grabbed it - if (eventQueueManager.ThreadsToExit > 0) - { - // Its crowded here so we'll shut down - eventQueueManager.ThreadsToExit--; - Stop(); - return; - } - else - { - // We have been asked to shut down - Stop(); - return; - } - } - } + DoProcessQueue(); + } + } + catch (ThreadAbortException tae) + { + if (lastScriptEngine != null) + lastScriptEngine.Log.Info("[" + ScriptEngineName + "]: ThreadAbortException while executing function."); + } + catch (Exception e) + { + if (lastScriptEngine != null) + lastScriptEngine.Log.Error("[" + ScriptEngineName + "]: Exception in EventQueueThreadLoop: " + e.ToString()); + } + } + } + catch (ThreadAbortException) + { + //myScriptEngine.Log.Info("[" + ScriptEngineName + "]: EventQueueManager Worker thread killed: " + tae.Message); + } + } + + public void DoProcessQueue() + { + foreach (ScriptEngine m_ScriptEngine in ScriptEngine.ScriptEngines) + { + lastScriptEngine = m_ScriptEngine; + // Every now and then check if we should shut down + //if (PleaseShutdown || EventQueueManager.ThreadsToExit > 0) + //{ + // // Someone should shut down, lets get exclusive lock + // lock (EventQueueManager.ThreadsToExitLock) + // { + // // Lets re-check in case someone grabbed it + // if (EventQueueManager.ThreadsToExit > 0) + // { + // // Its crowded here so we'll shut down + // EventQueueManager.ThreadsToExit--; + // Stop(); + // return; + // } + // else + // { + // // We have been asked to shut down + // Stop(); + // return; + // } + // } + //} + + //try + // { + EventQueueManager.QueueItemStruct QIS = BlankQIS; + bool GotItem = false; - //try - // { - EventQueueManager.QueueItemStruct QIS = BlankQIS; - bool GotItem = false; + //if (PleaseShutdown) + // return; - if (PleaseShutdown) - return; + if (m_ScriptEngine.m_EventQueueManager.eventQueue.Count == 0) + { + // Nothing to do? Sleep a bit waiting for something to do + Thread.Sleep(nothingToDoSleepms); + } + else + { + // Something in queue, process + //myScriptEngine.Log.Info("[" + ScriptEngineName + "]: Processing event for localID: " + QIS.localID + ", itemID: " + QIS.itemID + ", FunctionName: " + QIS.FunctionName); - if (eventQueueManager.eventQueue.Count == 0) + // OBJECT BASED LOCK - TWO THREADS WORKING ON SAME OBJECT IS NOT GOOD + lock (m_ScriptEngine.m_EventQueueManager.eventQueue) + { + GotItem = false; + for (int qc = 0; qc < m_ScriptEngine.m_EventQueueManager.eventQueue.Count; qc++) + { + // Get queue item + QIS = m_ScriptEngine.m_EventQueueManager.eventQueue.Dequeue(); + + // Check if object is being processed by someone else + if (m_ScriptEngine.m_EventQueueManager.TryLock(QIS.localID) == false) { - // Nothing to do? Sleep a bit waiting for something to do - Thread.Sleep(nothingToDoSleepms); + // Object is already being processed, requeue it + m_ScriptEngine.m_EventQueueManager.eventQueue.Enqueue(QIS); } else { - // Something in queue, process - //myScriptEngine.Log.Info("[" + ScriptEngineName + "]: Processing event for localID: " + QIS.localID + ", itemID: " + QIS.itemID + ", FunctionName: " + QIS.FunctionName); - - // OBJECT BASED LOCK - TWO THREADS WORKING ON SAME OBJECT IS NOT GOOD - lock (eventQueueManager.eventQueue) - { - GotItem = false; - for (int qc = 0; qc < eventQueueManager.eventQueue.Count; qc++) - { - // Get queue item - QIS = eventQueueManager.eventQueue.Dequeue(); - - // Check if object is being processed by someone else - if (eventQueueManager.TryLock(QIS.localID) == false) - { - // Object is already being processed, requeue it - eventQueueManager.eventQueue.Enqueue(QIS); - } - else - { - // We have lock on an object and can process it - GotItem = true; - break; - } - } - } + // We have lock on an object and can process it + GotItem = true; + break; + } + } + } - if (GotItem == true) - { - // Execute function - try - { -///cfk 2-7-08 dont need this right now and the default Linux build has DEBUG defined + if (GotItem == true) + { + // Execute function + try + { + ///cfk 2-7-08 dont need this right now and the default Linux build has DEBUG defined #if DEBUG - //eventQueueManager.m_ScriptEngine.Log.Debug("[" + ScriptEngineName + "]: " + - // "Executing event:\r\n" - // + "QIS.localID: " + QIS.localID - // + ", QIS.itemID: " + QIS.itemID - // + ", QIS.functionName: " + - // QIS.functionName); + //eventQueueManager.m_ScriptEngine.Log.Debug("[" + ScriptEngineName + "]: " + + // "Executing event:\r\n" + // + "QIS.localID: " + QIS.localID + // + ", QIS.itemID: " + QIS.itemID + // + ", QIS.functionName: " + + // QIS.functionName); #endif - LastExecutionStarted = DateTime.Now.Ticks; - KillCurrentScript = false; - InExecution = true; - eventQueueManager.m_ScriptEngine.m_ScriptManager.ExecuteEvent(QIS.localID, - QIS.itemID, - QIS.functionName, - QIS.llDetectParams, - QIS.param); - InExecution = false; - } - catch (Exception e) - { - InExecution = false; - // DISPLAY ERROR INWORLD - string text = "Error executing script function \"" + QIS.functionName + - "\":\r\n"; - if (e.InnerException != null) - { - // Send inner exception - text += e.InnerException.Message.ToString(); - } - else - { - text += "\r\n"; - // Send normal - text += e.Message.ToString(); - } - if (KillCurrentScript) - text += "\r\nScript will be deactivated!"; + LastExecutionStarted = DateTime.Now.Ticks; + KillCurrentScript = false; + InExecution = true; + m_ScriptEngine.m_ScriptManager.ExecuteEvent(QIS.localID, + QIS.itemID, + QIS.functionName, + QIS.llDetectParams, + QIS.param); + InExecution = false; + } + catch (Exception e) + { + InExecution = false; + // DISPLAY ERROR INWORLD + string text = "Error executing script function \"" + QIS.functionName + + "\":\r\n"; + if (e.InnerException != null) + { + // Send inner exception + text += e.InnerException.Message.ToString(); + } + else + { + text += "\r\n"; + // Send normal + text += e.Message.ToString(); + } + if (KillCurrentScript) + text += "\r\nScript will be deactivated!"; - try - { - if (text.Length > 1500) - text = text.Substring(0, 1500); - IScriptHost m_host = - eventQueueManager.m_ScriptEngine.World.GetSceneObjectPart(QIS.localID); - //if (m_host != null) - //{ - eventQueueManager.m_ScriptEngine.World.SimChat(Helpers.StringToField(text), - ChatTypeEnum.Say, 0, - m_host.AbsolutePosition, - m_host.Name, m_host.UUID); - } - catch - { - //} - //else - //{ - // T oconsole - eventQueueManager.m_ScriptEngine.Log.Error("[" + ScriptEngineName + "]: " + - "Unable to send text in-world:\r\n" + - text); - } - finally - { - // So we are done sending message in-world - if (KillCurrentScript) - { - eventQueueManager.m_ScriptEngine.m_ScriptManager.StopScript( - QIS.localID, QIS.itemID); - } - } - } - finally - { - InExecution = false; - eventQueueManager.ReleaseLock(QIS.localID); - } + try + { + if (text.Length > 1500) + text = text.Substring(0, 1500); + IScriptHost m_host = + m_ScriptEngine.World.GetSceneObjectPart(QIS.localID); + //if (m_host != null) + //{ + m_ScriptEngine.World.SimChat(Helpers.StringToField(text), + ChatTypeEnum.Say, 0, + m_host.AbsolutePosition, + m_host.Name, m_host.UUID); + } + catch + { + //} + //else + //{ + // T oconsole + m_ScriptEngine.m_EventQueueManager.m_ScriptEngine.Log.Error("[" + ScriptEngineName + "]: " + + "Unable to send text in-world:\r\n" + + text); + } + finally + { + // So we are done sending message in-world + if (KillCurrentScript) + { + m_ScriptEngine.m_EventQueueManager.m_ScriptEngine.m_ScriptManager.StopScript( + QIS.localID, QIS.itemID); } } } - } - catch (ThreadAbortException tae) - { - eventQueueManager.m_ScriptEngine.Log.Info("[" + ScriptEngineName + "]: ThreadAbortException while executing function."); - } - catch (Exception e) - { - eventQueueManager.m_ScriptEngine.Log.Error("[" + ScriptEngineName + "]: Exception in EventQueueThreadLoop: " + e.ToString()); + finally + { + InExecution = false; + m_ScriptEngine.m_EventQueueManager.ReleaseLock(QIS.localID); + } } } } - catch (ThreadAbortException) - { - //myScriptEngine.Log.Info("[" + ScriptEngineName + "]: EventQueueManager Worker thread killed: " + tae.Message); - } } - /// - /// If set to true then threads and stuff should try to make a graceful exit - /// - public bool PleaseShutdown - { - get { return _PleaseShutdown; } - set { _PleaseShutdown = value; } - } - private bool _PleaseShutdown = false; + ///// + ///// If set to true then threads and stuff should try to make a graceful exit + ///// + //public bool PleaseShutdown + //{ + // get { return _PleaseShutdown; } + // set { _PleaseShutdown = value; } + //} + //private bool _PleaseShutdown = false; } } -- cgit v1.1