123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 |
- /*
- * 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;
- using System.Reflection;
- using System.Threading;
- using log4net;
- using OpenSim.Framework;
- namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
- {
- /// <summary>
- /// This class does maintenance on script engine.
- /// </summary>
- public class MaintenanceThread : iScriptEngineFunctionModule
- {
- private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
- //public ScriptEngine m_ScriptEngine;
- private int MaintenanceLoopms;
- private int MaintenanceLoopTicks_ScriptLoadUnload;
- private int MaintenanceLoopTicks_Other;
- public MaintenanceThread()
- {
- //m_ScriptEngine = _ScriptEngine;
- ReadConfig();
- // Start maintenance thread
- StartMaintenanceThread();
- }
- ~MaintenanceThread()
- {
- StopMaintenanceThread();
- }
- public void ReadConfig()
- {
- // Bad hack, but we need a m_ScriptEngine :)
- lock (ScriptEngine.ScriptEngines)
- {
- foreach (ScriptEngine m_ScriptEngine in ScriptEngine.ScriptEngines)
- {
- MaintenanceLoopms = m_ScriptEngine.ScriptConfigSource.GetInt("MaintenanceLoopms", 50);
- MaintenanceLoopTicks_ScriptLoadUnload =
- m_ScriptEngine.ScriptConfigSource.GetInt("MaintenanceLoopTicks_ScriptLoadUnload", 1);
- MaintenanceLoopTicks_Other =
- m_ScriptEngine.ScriptConfigSource.GetInt("MaintenanceLoopTicks_Other", 10);
- return;
- }
- }
- }
- #region " Maintenance thread "
- /// <summary>
- /// Maintenance thread. Enforcing max execution time for example.
- /// </summary>
- public Thread MaintenanceThreadThread;
- /// <summary>
- /// Starts maintenance thread
- /// </summary>
- private void StartMaintenanceThread()
- {
- if (MaintenanceThreadThread == null)
- {
- MaintenanceThreadThread = new Thread(MaintenanceLoop);
- MaintenanceThreadThread.Name = "ScriptMaintenanceThread";
- MaintenanceThreadThread.IsBackground = true;
- MaintenanceThreadThread.Start();
- ThreadTracker.Add(MaintenanceThreadThread);
- }
- }
- /// <summary>
- /// Stops maintenance thread
- /// </summary>
- private void StopMaintenanceThread()
- {
- #if DEBUG
- //m_ScriptEngine.Log.Debug("[" + m_ScriptEngine.ScriptEngineName + "]: StopMaintenanceThread() called");
- #endif
- //PleaseShutdown = true;
- Thread.Sleep(100);
- try
- {
- if (MaintenanceThreadThread != null && MaintenanceThreadThread.IsAlive)
- {
- MaintenanceThreadThread.Abort();
- }
- }
- catch (Exception)
- {
- //m_ScriptEngine.Log.Error("[" + m_ScriptEngine.ScriptEngineName + "]: Exception stopping maintenence thread: " + ex.ToString());
- }
- }
- private ScriptEngine lastScriptEngine; // Keep track of what ScriptEngine instance we are at so we can give exception
- /// <summary>
- /// A thread should run in this loop and check all running scripts
- /// </summary>
- public void MaintenanceLoop()
- {
- //if (m_ScriptEngine.m_EventQueueManager.maxFunctionExecutionTimens < MaintenanceLoopms)
- // m_ScriptEngine.Log.Warn("[" + m_ScriptEngine.ScriptEngineName + "]: " +
- // "Configuration error: MaxEventExecutionTimeMs is less than MaintenanceLoopms. The Maintenance Loop will only check scripts once per run.");
- long Last_maxFunctionExecutionTimens = 0; // DateTime.Now.Ticks;
- long Last_ReReadConfigFilens = DateTime.Now.Ticks;
- int MaintenanceLoopTicks_ScriptLoadUnload_Count = 0;
- int MaintenanceLoopTicks_Other_Count = 0;
- bool MaintenanceLoopTicks_ScriptLoadUnload_ResetCount = false;
- bool MaintenanceLoopTicks_Other_ResetCount = false;
- while (true)
- {
- try
- {
- while (true)
- {
- Thread.Sleep(MaintenanceLoopms); // Sleep before next pass
- // Reset counters?
- if (MaintenanceLoopTicks_ScriptLoadUnload_ResetCount)
- {
- MaintenanceLoopTicks_ScriptLoadUnload_ResetCount = false;
- MaintenanceLoopTicks_ScriptLoadUnload_Count = 0;
- }
- if (MaintenanceLoopTicks_Other_ResetCount)
- {
- MaintenanceLoopTicks_Other_ResetCount = false;
- MaintenanceLoopTicks_Other_Count = 0;
- }
- // Increase our counters
- MaintenanceLoopTicks_ScriptLoadUnload_Count++;
- MaintenanceLoopTicks_Other_Count++;
- //lock (ScriptEngine.ScriptEngines)
- //{
- foreach (ScriptEngine m_ScriptEngine in new ArrayList(ScriptEngine.ScriptEngines))
- {
- lastScriptEngine = m_ScriptEngine;
- // Re-reading config every x seconds
- if (MaintenanceLoopTicks_Other_Count >= MaintenanceLoopTicks_Other)
- {
- MaintenanceLoopTicks_Other_ResetCount = true;
- if (m_ScriptEngine.RefreshConfigFilens > 0)
- {
- // Check if its time to re-read config
- if (DateTime.Now.Ticks - Last_ReReadConfigFilens >
- m_ScriptEngine.RefreshConfigFilens)
- {
- //Console.WriteLine("Time passed: " + (DateTime.Now.Ticks - Last_ReReadConfigFilens) + ">" + m_ScriptEngine.RefreshConfigFilens);
- // Its time to re-read config file
- m_ScriptEngine.ReadConfig();
- Last_ReReadConfigFilens = DateTime.Now.Ticks; // Reset time
- }
- // Adjust number of running script threads if not correct
- if (m_ScriptEngine.m_EventQueueManager != null)
- m_ScriptEngine.m_EventQueueManager.AdjustNumberOfScriptThreads();
- // Check if any script has exceeded its max execution time
- if (EventQueueManager.EnforceMaxExecutionTime)
- {
- // We are enforcing execution time
- if (DateTime.Now.Ticks - Last_maxFunctionExecutionTimens >
- EventQueueManager.maxFunctionExecutionTimens)
- {
- // Its time to check again
- m_ScriptEngine.m_EventQueueManager.CheckScriptMaxExecTime(); // Do check
- Last_maxFunctionExecutionTimens = DateTime.Now.Ticks; // Reset time
- }
- }
- }
- }
- if (MaintenanceLoopTicks_ScriptLoadUnload_Count >= MaintenanceLoopTicks_ScriptLoadUnload)
- {
- MaintenanceLoopTicks_ScriptLoadUnload_ResetCount = true;
- // LOAD / UNLOAD SCRIPTS
- if (m_ScriptEngine.m_ScriptManager != null)
- m_ScriptEngine.m_ScriptManager.DoScriptLoadUnload();
- }
- }
- //}
- }
- }
- catch(ThreadAbortException)
- {
- m_log.Error("Thread aborted in MaintenanceLoopThread. If this is during shutdown, please ignore");
- }
- catch (Exception ex)
- {
- m_log.ErrorFormat("Exception in MaintenanceLoopThread. Thread will recover after 5 sec throttle. Exception: {0}", ex.ToString());
- }
- }
- }
- #endregion
- ///// <summary>
- ///// If set to true then threads and stuff should try to make a graceful exit
- ///// </summary>
- //public bool PleaseShutdown
- //{
- // get { return _PleaseShutdown; }
- // set { _PleaseShutdown = value; }
- //}
- //private bool _PleaseShutdown = false;
- }
- }
|