From a6726b0c9de4ef875348f9dcbf21a9c93bde8a09 Mon Sep 17 00:00:00 2001 From: Tedd Hansen Date: Fri, 1 Feb 2008 22:18:55 +0000 Subject: SCRIPT SUPPORT IS STILL BROKEN. Bugfix: Scripts exceeding max and set to be killed were not killed, only removed. Added ability to re-read configuration while OpenSim is running All regions now sharing one MaintenanceThread New MaintenanceThread: - checks for script execution timeout - re-reads config - starts/stops threads if thread active count becomes too high/low compared to config Speed increase on event execution: - Reuse of try{}catch{} blocks - Time calculation on event execution --- .../ScriptEngineBase/EventQueueThreadClass.cs | 220 ++++++++++++--------- 1 file changed, 127 insertions(+), 93 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 57caad5..e610c36 100644 --- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs +++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs @@ -19,7 +19,7 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase /// private int nothingToDoSleepms;// = 50; - public DateTime LastExecutionStarted; + public long LastExecutionStarted; public bool InExecution = false; public bool KillCurrentScript = false; @@ -109,120 +109,154 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase //myScriptEngine.m_logger.Verbose("ScriptEngine", "EventQueueManager Worker thread spawned"); try { - EventQueueManager.QueueItemStruct BlankQIS = new EventQueueManager.QueueItemStruct(); - while (true) + while (true) { try { - EventQueueManager.QueueItemStruct QIS = BlankQIS; - bool GotItem = false; - - if (eventQueueManager.eventQueue.Count == 0) - { - // Nothing to do? Sleep a bit waiting for something to do - Thread.Sleep(nothingToDoSleepms); - } - else + EventQueueManager.QueueItemStruct BlankQIS = new EventQueueManager.QueueItemStruct(); + while (true) { - // Something in queue, process - //myScriptEngine.m_logger.Verbose("ScriptEngine", "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.queueLock) + // Every now and then check if we should shut down + if (eventQueueManager.ThreadsToExit > 0) { - GotItem = false; - for (int qc = 0; qc < eventQueueManager.eventQueue.Count; qc++) + // Someone should shut down, lets get exclusive lock + lock (eventQueueManager.ThreadsToExitLock) { - // 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 + // Lets re-check in case someone grabbed it + if (eventQueueManager.ThreadsToExit > 0) { - // We have lock on an object and can process it - GotItem = true; - break; + // We are go for shutdown + eventQueueManager.ThreadsToExit--; + Shutdown(); + return; } - } // go through queue - } // lock + } + } - if (GotItem == true) + + //try + // { + EventQueueManager.QueueItemStruct QIS = BlankQIS; + bool GotItem = false; + + if (eventQueueManager.eventQueue.Count == 0) { - // Execute function - try - { -#if DEBUG - eventQueueManager.m_ScriptEngine.Log.Debug("ScriptEngine", "Executing event:\r\n" - + "QIS.localID: " + QIS.localID - + ", QIS.itemID: " + QIS.itemID - + ", QIS.functionName: " + QIS.functionName); -#endif - LastExecutionStarted = DateTime.Now; - 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) + // Nothing to do? Sleep a bit waiting for something to do + Thread.Sleep(nothingToDoSleepms); + } + else + { + // Something in queue, process + //myScriptEngine.m_logger.Verbose("ScriptEngine", "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.queueLock) { - InExecution = false; - // DISPLAY ERROR INWORLD - string text = "Error executing script function \"" + QIS.functionName + "\":\r\n"; - if (e.InnerException != null) + GotItem = false; + for (int qc = 0; qc < eventQueueManager.eventQueue.Count; qc++) { - // 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!"; + // 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; + } + } // go through queue + } // lock + if (GotItem == true) + { + // Execute function 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("ScriptEngine", - "Unable to send text in-world:\r\n" + text); +#if DEBUG + eventQueueManager.m_ScriptEngine.Log.Debug("ScriptEngine", + "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; } - finally + catch (Exception e) { - // So we are done sending message in-world + 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 { - eventQueueManager.m_ScriptEngine.m_ScriptManager.RemoveScript(QIS.localID, QIS.itemID); + //} + //else + //{ + // T oconsole + eventQueueManager.m_ScriptEngine.Log.Error("ScriptEngine", + "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); + } } - finally - { - InExecution = false; - eventQueueManager.ReleaseLock(QIS.localID); - } - } - } // Something in queue + } // Something in queue + } } catch (ThreadAbortException tae) { -- cgit v1.1