aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/DotNetEngine/MaintenanceThread.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ScriptEngine/DotNetEngine/MaintenanceThread.cs')
-rw-r--r--OpenSim/Region/ScriptEngine/DotNetEngine/MaintenanceThread.cs243
1 files changed, 243 insertions, 0 deletions
diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/MaintenanceThread.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/MaintenanceThread.cs
new file mode 100644
index 0000000..6c1528f
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/DotNetEngine/MaintenanceThread.cs
@@ -0,0 +1,243 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Reflection;
31using System.Threading;
32using log4net;
33using OpenSim.Framework;
34
35namespace OpenSim.Region.ScriptEngine.DotNetEngine
36{
37 /// <summary>
38 /// This class does maintenance on script engine.
39 /// </summary>
40 public class MaintenanceThread : iScriptEngineFunctionModule
41 {
42
43 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
44
45 //public ScriptEngine m_ScriptEngine;
46 private int MaintenanceLoopms;
47 private int MaintenanceLoopTicks_ScriptLoadUnload;
48 private int MaintenanceLoopTicks_Other;
49
50
51 public MaintenanceThread()
52 {
53 //m_ScriptEngine = _ScriptEngine;
54
55 ReadConfig();
56
57 // Start maintenance thread
58 StartMaintenanceThread();
59 }
60
61 ~MaintenanceThread()
62 {
63 StopMaintenanceThread();
64 }
65
66 public void ReadConfig()
67 {
68 // Bad hack, but we need a m_ScriptEngine :)
69 lock (ScriptEngine.ScriptEngines)
70 {
71 foreach (ScriptEngine m_ScriptEngine in ScriptEngine.ScriptEngines)
72 {
73 MaintenanceLoopms = m_ScriptEngine.ScriptConfigSource.GetInt("MaintenanceLoopms", 50);
74 MaintenanceLoopTicks_ScriptLoadUnload =
75 m_ScriptEngine.ScriptConfigSource.GetInt("MaintenanceLoopTicks_ScriptLoadUnload", 1);
76 MaintenanceLoopTicks_Other =
77 m_ScriptEngine.ScriptConfigSource.GetInt("MaintenanceLoopTicks_Other", 10);
78
79 return;
80 }
81 }
82 }
83
84 #region " Maintenance thread "
85 /// <summary>
86 /// Maintenance thread. Enforcing max execution time for example.
87 /// </summary>
88 public Thread MaintenanceThreadThread;
89
90 /// <summary>
91 /// Starts maintenance thread
92 /// </summary>
93 private void StartMaintenanceThread()
94 {
95 if (MaintenanceThreadThread == null)
96 {
97 MaintenanceThreadThread = new Thread(MaintenanceLoop);
98 MaintenanceThreadThread.Name = "ScriptMaintenanceThread";
99 MaintenanceThreadThread.IsBackground = true;
100 MaintenanceThreadThread.Start();
101 ThreadTracker.Add(MaintenanceThreadThread);
102 }
103 }
104
105 /// <summary>
106 /// Stops maintenance thread
107 /// </summary>
108 private void StopMaintenanceThread()
109 {
110#if DEBUG
111 //m_ScriptEngine.Log.Debug("[" + m_ScriptEngine.ScriptEngineName + "]: StopMaintenanceThread() called");
112#endif
113 //PleaseShutdown = true;
114 Thread.Sleep(100);
115 try
116 {
117 if (MaintenanceThreadThread != null && MaintenanceThreadThread.IsAlive)
118 {
119 MaintenanceThreadThread.Abort();
120 }
121 }
122 catch (Exception)
123 {
124 //m_ScriptEngine.Log.Error("[" + m_ScriptEngine.ScriptEngineName + "]: Exception stopping maintenence thread: " + ex.ToString());
125 }
126 }
127
128 // private ScriptEngine lastScriptEngine; // Keep track of what ScriptEngine instance we are at so we can give exception
129 /// <summary>
130 /// A thread should run in this loop and check all running scripts
131 /// </summary>
132 public void MaintenanceLoop()
133 {
134 //if (m_ScriptEngine.m_EventQueueManager.maxFunctionExecutionTimens < MaintenanceLoopms)
135 // m_ScriptEngine.Log.Warn("[" + m_ScriptEngine.ScriptEngineName + "]: " +
136 // "Configuration error: MaxEventExecutionTimeMs is less than MaintenanceLoopms. The Maintenance Loop will only check scripts once per run.");
137
138 long Last_maxFunctionExecutionTimens = 0; // DateTime.Now.Ticks;
139 long Last_ReReadConfigFilens = DateTime.Now.Ticks;
140 int MaintenanceLoopTicks_ScriptLoadUnload_Count = 0;
141 int MaintenanceLoopTicks_Other_Count = 0;
142 bool MaintenanceLoopTicks_ScriptLoadUnload_ResetCount = false;
143 bool MaintenanceLoopTicks_Other_ResetCount = false;
144
145 while (true)
146 {
147 try
148 {
149 while (true)
150 {
151 Thread.Sleep(MaintenanceLoopms); // Sleep before next pass
152
153 // Reset counters?
154 if (MaintenanceLoopTicks_ScriptLoadUnload_ResetCount)
155 {
156 MaintenanceLoopTicks_ScriptLoadUnload_ResetCount = false;
157 MaintenanceLoopTicks_ScriptLoadUnload_Count = 0;
158 }
159 if (MaintenanceLoopTicks_Other_ResetCount)
160 {
161 MaintenanceLoopTicks_Other_ResetCount = false;
162 MaintenanceLoopTicks_Other_Count = 0;
163 }
164
165 // Increase our counters
166 MaintenanceLoopTicks_ScriptLoadUnload_Count++;
167 MaintenanceLoopTicks_Other_Count++;
168
169
170 //lock (ScriptEngine.ScriptEngines)
171 //{
172 foreach (ScriptEngine m_ScriptEngine in new ArrayList(ScriptEngine.ScriptEngines))
173 {
174 // lastScriptEngine = m_ScriptEngine;
175 // Re-reading config every x seconds
176 if (MaintenanceLoopTicks_Other_Count >= MaintenanceLoopTicks_Other)
177 {
178 MaintenanceLoopTicks_Other_ResetCount = true;
179 if (m_ScriptEngine.RefreshConfigFilens > 0)
180 {
181 // Check if its time to re-read config
182 if (DateTime.Now.Ticks - Last_ReReadConfigFilens >
183 m_ScriptEngine.RefreshConfigFilens)
184 {
185 //Console.WriteLine("Time passed: " + (DateTime.Now.Ticks - Last_ReReadConfigFilens) + ">" + m_ScriptEngine.RefreshConfigFilens);
186 // Its time to re-read config file
187 m_ScriptEngine.ReadConfig();
188 Last_ReReadConfigFilens = DateTime.Now.Ticks; // Reset time
189 }
190
191
192 // Adjust number of running script threads if not correct
193 if (m_ScriptEngine.m_EventQueueManager != null)
194 m_ScriptEngine.m_EventQueueManager.AdjustNumberOfScriptThreads();
195
196 // Check if any script has exceeded its max execution time
197 if (EventQueueManager.EnforceMaxExecutionTime)
198 {
199 // We are enforcing execution time
200 if (DateTime.Now.Ticks - Last_maxFunctionExecutionTimens >
201 EventQueueManager.maxFunctionExecutionTimens)
202 {
203 // Its time to check again
204 m_ScriptEngine.m_EventQueueManager.CheckScriptMaxExecTime(); // Do check
205 Last_maxFunctionExecutionTimens = DateTime.Now.Ticks; // Reset time
206 }
207 }
208 }
209 }
210 if (MaintenanceLoopTicks_ScriptLoadUnload_Count >= MaintenanceLoopTicks_ScriptLoadUnload)
211 {
212 MaintenanceLoopTicks_ScriptLoadUnload_ResetCount = true;
213 // LOAD / UNLOAD SCRIPTS
214 if (m_ScriptEngine.m_ScriptManager != null)
215 m_ScriptEngine.m_ScriptManager.DoScriptLoadUnload();
216 }
217 }
218 //}
219 }
220 }
221 catch(ThreadAbortException)
222 {
223 m_log.Error("Thread aborted in MaintenanceLoopThread. If this is during shutdown, please ignore");
224 }
225 catch (Exception ex)
226 {
227 m_log.ErrorFormat("Exception in MaintenanceLoopThread. Thread will recover after 5 sec throttle. Exception: {0}", ex.ToString());
228 }
229 }
230 }
231 #endregion
232
233 ///// <summary>
234 ///// If set to true then threads and stuff should try to make a graceful exit
235 ///// </summary>
236 //public bool PleaseShutdown
237 //{
238 // get { return _PleaseShutdown; }
239 // set { _PleaseShutdown = value; }
240 //}
241 //private bool _PleaseShutdown = false;
242 }
243}