diff options
Diffstat (limited to 'OpenSim/Region/ScriptEngine/Shared/Instance')
-rw-r--r-- | OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs | 419 |
1 files changed, 200 insertions, 219 deletions
diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs index bc1902b..6e36742 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs | |||
@@ -56,36 +56,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
56 | public class ScriptInstance : MarshalByRefObject, IScriptInstance | 56 | public class ScriptInstance : MarshalByRefObject, IScriptInstance |
57 | { | 57 | { |
58 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 58 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
59 | 59 | ||
60 | private IScriptEngine m_Engine; | 60 | /// <summary> |
61 | private IScriptWorkItem m_CurrentResult = null; | 61 | /// The current work item if an event for this script is running or waiting to run, |
62 | private Queue m_EventQueue = new Queue(32); | 62 | /// </summary> |
63 | private bool m_RunEvents = false; | 63 | /// <remarks> |
64 | private UUID m_ItemID; | 64 | /// Null if there is no running or waiting to run event. Must be changed only under an EventQueue lock. |
65 | private uint m_LocalID; | 65 | /// </remarks> |
66 | private UUID m_ObjectID; | 66 | private IScriptWorkItem m_CurrentWorkItem; |
67 | private UUID m_AssetID; | 67 | |
68 | private IScript m_Script; | 68 | private IScript m_Script; |
69 | private UUID m_AppDomain; | ||
70 | private DetectParams[] m_DetectParams; | 69 | private DetectParams[] m_DetectParams; |
71 | private bool m_TimerQueued; | 70 | private bool m_TimerQueued; |
72 | private DateTime m_EventStart; | 71 | private DateTime m_EventStart; |
73 | private bool m_InEvent; | 72 | private bool m_InEvent; |
74 | private string m_PrimName; | ||
75 | private string m_ScriptName; | ||
76 | private string m_Assembly; | 73 | private string m_Assembly; |
77 | private int m_StartParam; | ||
78 | private string m_CurrentEvent = String.Empty; | 74 | private string m_CurrentEvent = String.Empty; |
79 | private bool m_InSelfDelete; | 75 | private bool m_InSelfDelete; |
80 | private int m_MaxScriptQueue; | 76 | private int m_MaxScriptQueue; |
81 | private bool m_SaveState = true; | 77 | private bool m_SaveState = true; |
82 | private bool m_ShuttingDown; | ||
83 | private int m_ControlEventsInQueue; | 78 | private int m_ControlEventsInQueue; |
84 | private int m_LastControlLevel; | 79 | private int m_LastControlLevel; |
85 | private bool m_CollisionInQueue; | 80 | private bool m_CollisionInQueue; |
86 | private TaskInventoryItem m_thisScriptTask; | 81 | |
87 | // The following is for setting a minimum delay between events | 82 | // The following is for setting a minimum delay between events |
88 | private double m_minEventDelay; | 83 | private double m_minEventDelay; |
84 | |||
89 | private long m_eventDelayTicks; | 85 | private long m_eventDelayTicks; |
90 | private long m_nextEventTimeTicks; | 86 | private long m_nextEventTimeTicks; |
91 | private bool m_startOnInit = true; | 87 | private bool m_startOnInit = true; |
@@ -96,21 +92,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
96 | private UUID m_CurrentStateHash; | 92 | private UUID m_CurrentStateHash; |
97 | private UUID m_RegionID; | 93 | private UUID m_RegionID; |
98 | 94 | ||
99 | private Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> | 95 | public Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> LineMap { get; set; } |
100 | m_LineMap; | ||
101 | |||
102 | public Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> | ||
103 | LineMap | ||
104 | { | ||
105 | get { return m_LineMap; } | ||
106 | set { m_LineMap = value; } | ||
107 | } | ||
108 | 96 | ||
109 | private Dictionary<string,IScriptApi> m_Apis = new Dictionary<string,IScriptApi>(); | 97 | private Dictionary<string,IScriptApi> m_Apis = new Dictionary<string,IScriptApi>(); |
110 | 98 | ||
111 | // Script state | ||
112 | private string m_State = "default"; | ||
113 | |||
114 | public Object[] PluginData = new Object[0]; | 99 | public Object[] PluginData = new Object[0]; |
115 | 100 | ||
116 | /// <summary> | 101 | /// <summary> |
@@ -133,11 +118,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
133 | } | 118 | } |
134 | } | 119 | } |
135 | 120 | ||
136 | public bool Running | 121 | public bool Running { get; set; } |
137 | { | ||
138 | get { return m_RunEvents; } | ||
139 | set { m_RunEvents = value; } | ||
140 | } | ||
141 | 122 | ||
142 | public bool Suspended | 123 | public bool Suspended |
143 | { | 124 | { |
@@ -153,11 +134,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
153 | 134 | ||
154 | if (wasSuspended && !m_Suspended) | 135 | if (wasSuspended && !m_Suspended) |
155 | { | 136 | { |
156 | lock (m_EventQueue) | 137 | lock (EventQueue) |
157 | { | 138 | { |
158 | // Need to place ourselves back in a work item if there are events to process | 139 | // Need to place ourselves back in a work item if there are events to process |
159 | if ((m_EventQueue.Count > 0) && m_RunEvents && (!m_ShuttingDown)) | 140 | if (EventQueue.Count > 0 && Running && !ShuttingDown) |
160 | m_CurrentResult = m_Engine.QueueEventHandler(this); | 141 | m_CurrentWorkItem = Engine.QueueEventHandler(this); |
161 | } | 142 | } |
162 | } | 143 | } |
163 | } | 144 | } |
@@ -165,79 +146,48 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
165 | } | 146 | } |
166 | private bool m_Suspended; | 147 | private bool m_Suspended; |
167 | 148 | ||
168 | public bool ShuttingDown | 149 | public bool ShuttingDown { get; set; } |
169 | { | ||
170 | get { return m_ShuttingDown; } | ||
171 | set { m_ShuttingDown = value; } | ||
172 | } | ||
173 | 150 | ||
174 | public string State | 151 | public string State { get; set; } |
175 | { | ||
176 | get { return m_State; } | ||
177 | set { m_State = value; } | ||
178 | } | ||
179 | 152 | ||
180 | public IScriptEngine Engine | 153 | public IScriptEngine Engine { get; private set; } |
181 | { | ||
182 | get { return m_Engine; } | ||
183 | } | ||
184 | 154 | ||
185 | public UUID AppDomain | 155 | public UUID AppDomain { get; set; } |
186 | { | ||
187 | get { return m_AppDomain; } | ||
188 | set { m_AppDomain = value; } | ||
189 | } | ||
190 | 156 | ||
191 | public string PrimName | 157 | public string PrimName { get; private set; } |
192 | { | ||
193 | get { return m_PrimName; } | ||
194 | } | ||
195 | 158 | ||
196 | public string ScriptName | 159 | public string ScriptName { get; private set; } |
197 | { | ||
198 | get { return m_ScriptName; } | ||
199 | } | ||
200 | 160 | ||
201 | public UUID ItemID | 161 | public UUID ItemID { get; private set; } |
202 | { | ||
203 | get { return m_ItemID; } | ||
204 | } | ||
205 | 162 | ||
206 | public UUID ObjectID | 163 | public UUID ObjectID { get; private set; } |
207 | { | ||
208 | get { return m_ObjectID; } | ||
209 | } | ||
210 | 164 | ||
211 | public uint LocalID | 165 | public uint LocalID { get; private set; } |
212 | { | ||
213 | get { return m_LocalID; } | ||
214 | } | ||
215 | 166 | ||
216 | public UUID AssetID | 167 | public UUID RootObjectID { get; private set; } |
217 | { | ||
218 | get { return m_AssetID; } | ||
219 | } | ||
220 | 168 | ||
221 | public Queue EventQueue | 169 | public uint RootLocalID { get; private set; } |
222 | { | ||
223 | get { return m_EventQueue; } | ||
224 | } | ||
225 | 170 | ||
226 | public void ClearQueue() | 171 | public UUID AssetID { get; private set; } |
227 | { | ||
228 | m_TimerQueued = false; | ||
229 | m_EventQueue.Clear(); | ||
230 | } | ||
231 | 172 | ||
232 | public int StartParam | 173 | public Queue EventQueue { get; private set; } |
233 | { | 174 | |
234 | get { return m_StartParam; } | 175 | public int StartParam { get; set; } |
235 | set { m_StartParam = value; } | 176 | |
236 | } | 177 | public TaskInventoryItem ScriptTask { get; private set; } |
178 | |||
179 | public DateTime TimeStarted { get; private set; } | ||
180 | |||
181 | public long MeasurementPeriodTickStart { get; private set; } | ||
237 | 182 | ||
238 | public TaskInventoryItem ScriptTask | 183 | public long MeasurementPeriodExecutionTime { get; private set; } |
184 | |||
185 | public static readonly long MaxMeasurementPeriod = 30 * TimeSpan.TicksPerMinute; | ||
186 | |||
187 | public void ClearQueue() | ||
239 | { | 188 | { |
240 | get { return m_thisScriptTask; } | 189 | m_TimerQueued = false; |
190 | EventQueue.Clear(); | ||
241 | } | 191 | } |
242 | 192 | ||
243 | public ScriptInstance(IScriptEngine engine, SceneObjectPart part, | 193 | public ScriptInstance(IScriptEngine engine, SceneObjectPart part, |
@@ -246,16 +196,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
246 | int startParam, bool postOnRez, StateSource stateSource, | 196 | int startParam, bool postOnRez, StateSource stateSource, |
247 | int maxScriptQueue) | 197 | int maxScriptQueue) |
248 | { | 198 | { |
249 | m_Engine = engine; | 199 | State = "default"; |
250 | 200 | EventQueue = new Queue(32); | |
251 | m_LocalID = part.LocalId; | 201 | |
252 | m_ObjectID = part.UUID; | 202 | Engine = engine; |
253 | m_ItemID = itemID; | 203 | LocalID = part.LocalId; |
254 | m_AssetID = assetID; | 204 | ObjectID = part.UUID; |
255 | m_PrimName = primName; | 205 | RootLocalID = part.ParentGroup.LocalId; |
256 | m_ScriptName = scriptName; | 206 | RootObjectID = part.ParentGroup.UUID; |
207 | ItemID = itemID; | ||
208 | AssetID = assetID; | ||
209 | PrimName = primName; | ||
210 | ScriptName = scriptName; | ||
257 | m_Assembly = assembly; | 211 | m_Assembly = assembly; |
258 | m_StartParam = startParam; | 212 | StartParam = startParam; |
259 | m_MaxScriptQueue = maxScriptQueue; | 213 | m_MaxScriptQueue = maxScriptQueue; |
260 | m_stateSource = stateSource; | 214 | m_stateSource = stateSource; |
261 | m_postOnRez = postOnRez; | 215 | m_postOnRez = postOnRez; |
@@ -266,9 +220,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
266 | { | 220 | { |
267 | lock (part.TaskInventory) | 221 | lock (part.TaskInventory) |
268 | { | 222 | { |
269 | if (part.TaskInventory.ContainsKey(m_ItemID)) | 223 | if (part.TaskInventory.ContainsKey(ItemID)) |
270 | { | 224 | { |
271 | m_thisScriptTask = part.TaskInventory[m_ItemID]; | 225 | ScriptTask = part.TaskInventory[ItemID]; |
272 | } | 226 | } |
273 | } | 227 | } |
274 | } | 228 | } |
@@ -278,20 +232,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
278 | foreach (string api in am.GetApis()) | 232 | foreach (string api in am.GetApis()) |
279 | { | 233 | { |
280 | m_Apis[api] = am.CreateApi(api); | 234 | m_Apis[api] = am.CreateApi(api); |
281 | m_Apis[api].Initialize(engine, part, m_LocalID, itemID); | 235 | m_Apis[api].Initialize(engine, part, LocalID, itemID); |
282 | } | 236 | } |
283 | 237 | ||
284 | try | 238 | try |
285 | { | 239 | { |
286 | if (dom != System.AppDomain.CurrentDomain) | 240 | if (dom != System.AppDomain.CurrentDomain) |
287 | m_Script = (IScript)dom.CreateInstanceAndUnwrap( | 241 | m_Script = (IScript)dom.CreateInstanceAndUnwrap( |
288 | Path.GetFileNameWithoutExtension(assembly), | 242 | Path.GetFileNameWithoutExtension(assembly), |
289 | "SecondLife.Script"); | 243 | "SecondLife.Script"); |
290 | else | 244 | else |
291 | m_Script = (IScript)Assembly.Load( | 245 | m_Script = (IScript)Assembly.Load( |
292 | Path.GetFileNameWithoutExtension(assembly)).CreateInstance( | 246 | Path.GetFileNameWithoutExtension(assembly)).CreateInstance( |
293 | "SecondLife.Script"); | 247 | "SecondLife.Script"); |
294 | |||
295 | 248 | ||
296 | //ILease lease = (ILease)RemotingServices.GetLifetimeService(m_Script as ScriptBaseClass); | 249 | //ILease lease = (ILease)RemotingServices.GetLifetimeService(m_Script as ScriptBaseClass); |
297 | //RemotingServices.GetLifetimeService(m_Script as ScriptBaseClass); | 250 | //RemotingServices.GetLifetimeService(m_Script as ScriptBaseClass); |
@@ -313,7 +266,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
313 | 266 | ||
314 | // // m_log.Debug("[Script] Script instance created"); | 267 | // // m_log.Debug("[Script] Script instance created"); |
315 | 268 | ||
316 | part.SetScriptEvents(m_ItemID, | 269 | part.SetScriptEvents(ItemID, |
317 | (int)m_Script.GetStateEventFlags(State)); | 270 | (int)m_Script.GetStateEventFlags(State)); |
318 | } | 271 | } |
319 | catch (Exception e) | 272 | catch (Exception e) |
@@ -328,7 +281,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
328 | m_SaveState = true; | 281 | m_SaveState = true; |
329 | 282 | ||
330 | string savedState = Path.Combine(Path.GetDirectoryName(assembly), | 283 | string savedState = Path.Combine(Path.GetDirectoryName(assembly), |
331 | m_ItemID.ToString() + ".state"); | 284 | ItemID.ToString() + ".state"); |
332 | if (File.Exists(savedState)) | 285 | if (File.Exists(savedState)) |
333 | { | 286 | { |
334 | string xml = String.Empty; | 287 | string xml = String.Empty; |
@@ -352,24 +305,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
352 | 305 | ||
353 | ScriptSerializer.Deserialize(xml, this); | 306 | ScriptSerializer.Deserialize(xml, this); |
354 | 307 | ||
355 | AsyncCommandManager.CreateFromData(m_Engine, | 308 | AsyncCommandManager.CreateFromData(Engine, |
356 | m_LocalID, m_ItemID, m_ObjectID, | 309 | LocalID, ItemID, ObjectID, |
357 | PluginData); | 310 | PluginData); |
358 | 311 | ||
359 | // m_log.DebugFormat("[Script] Successfully retrieved state for script {0}.{1}", m_PrimName, m_ScriptName); | 312 | // m_log.DebugFormat("[Script] Successfully retrieved state for script {0}.{1}", PrimName, m_ScriptName); |
360 | 313 | ||
361 | part.SetScriptEvents(m_ItemID, | 314 | part.SetScriptEvents(ItemID, |
362 | (int)m_Script.GetStateEventFlags(State)); | 315 | (int)m_Script.GetStateEventFlags(State)); |
363 | 316 | ||
364 | if (m_RunEvents && (!m_ShuttingDown)) | 317 | Running = false; |
365 | { | 318 | |
366 | m_RunEvents = false; | 319 | if (ShuttingDown) |
367 | } | ||
368 | else | ||
369 | { | ||
370 | m_RunEvents = false; | ||
371 | m_startOnInit = false; | 320 | m_startOnInit = false; |
372 | } | ||
373 | 321 | ||
374 | // we get new rez events on sim restart, too | 322 | // we get new rez events on sim restart, too |
375 | // but if there is state, then we fire the change | 323 | // but if there is state, then we fire the change |
@@ -378,7 +326,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
378 | // We loaded state, don't force a re-save | 326 | // We loaded state, don't force a re-save |
379 | m_SaveState = false; | 327 | m_SaveState = false; |
380 | m_startedFromSavedState = true; | 328 | m_startedFromSavedState = true; |
381 | |||
382 | } | 329 | } |
383 | } | 330 | } |
384 | else | 331 | else |
@@ -397,7 +344,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
397 | } | 344 | } |
398 | // else | 345 | // else |
399 | // { | 346 | // { |
400 | // ScenePresence presence = m_Engine.World.GetScenePresence(part.OwnerID); | 347 | // ScenePresence presence = Engine.World.GetScenePresence(part.OwnerID); |
401 | 348 | ||
402 | // if (presence != null && (!postOnRez)) | 349 | // if (presence != null && (!postOnRez)) |
403 | // presence.ControllingClient.SendAgentAlertMessage("Compile successful", false); | 350 | // presence.ControllingClient.SendAgentAlertMessage("Compile successful", false); |
@@ -415,7 +362,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
415 | if (m_postOnRez) | 362 | if (m_postOnRez) |
416 | { | 363 | { |
417 | PostEvent(new EventParams("on_rez", | 364 | PostEvent(new EventParams("on_rez", |
418 | new Object[] {new LSL_Types.LSLInteger(m_StartParam)}, new DetectParams[0])); | 365 | new Object[] {new LSL_Types.LSLInteger(StartParam)}, new DetectParams[0])); |
419 | } | 366 | } |
420 | 367 | ||
421 | if (m_stateSource == StateSource.AttachedRez) | 368 | if (m_stateSource == StateSource.AttachedRez) |
@@ -449,7 +396,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
449 | if (m_postOnRez) | 396 | if (m_postOnRez) |
450 | { | 397 | { |
451 | PostEvent(new EventParams("on_rez", | 398 | PostEvent(new EventParams("on_rez", |
452 | new Object[] {new LSL_Types.LSLInteger(m_StartParam)}, new DetectParams[0])); | 399 | new Object[] {new LSL_Types.LSLInteger(StartParam)}, new DetectParams[0])); |
453 | } | 400 | } |
454 | 401 | ||
455 | if (m_stateSource == StateSource.AttachedRez) | 402 | if (m_stateSource == StateSource.AttachedRez) |
@@ -463,7 +410,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
463 | 410 | ||
464 | private void ReleaseControls() | 411 | private void ReleaseControls() |
465 | { | 412 | { |
466 | SceneObjectPart part = m_Engine.World.GetSceneObjectPart(m_LocalID); | 413 | SceneObjectPart part = Engine.World.GetSceneObjectPart(LocalID); |
467 | 414 | ||
468 | if (part != null) | 415 | if (part != null) |
469 | { | 416 | { |
@@ -471,18 +418,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
471 | UUID permsGranter; | 418 | UUID permsGranter; |
472 | lock (part.TaskInventory) | 419 | lock (part.TaskInventory) |
473 | { | 420 | { |
474 | if (!part.TaskInventory.ContainsKey(m_ItemID)) | 421 | if (!part.TaskInventory.ContainsKey(ItemID)) |
475 | return; | 422 | return; |
476 | 423 | ||
477 | permsGranter = part.TaskInventory[m_ItemID].PermsGranter; | 424 | permsGranter = part.TaskInventory[ItemID].PermsGranter; |
478 | permsMask = part.TaskInventory[m_ItemID].PermsMask; | 425 | permsMask = part.TaskInventory[ItemID].PermsMask; |
479 | } | 426 | } |
480 | 427 | ||
481 | if ((permsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0) | 428 | if ((permsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0) |
482 | { | 429 | { |
483 | ScenePresence presence = m_Engine.World.GetScenePresence(permsGranter); | 430 | ScenePresence presence = Engine.World.GetScenePresence(permsGranter); |
484 | if (presence != null) | 431 | if (presence != null) |
485 | presence.UnRegisterControlEventsToScript(m_LocalID, m_ItemID); | 432 | presence.UnRegisterControlEventsToScript(LocalID, ItemID); |
486 | } | 433 | } |
487 | } | 434 | } |
488 | } | 435 | } |
@@ -490,13 +437,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
490 | public void DestroyScriptInstance() | 437 | public void DestroyScriptInstance() |
491 | { | 438 | { |
492 | ReleaseControls(); | 439 | ReleaseControls(); |
493 | AsyncCommandManager.RemoveScript(m_Engine, m_LocalID, m_ItemID); | 440 | AsyncCommandManager.RemoveScript(Engine, LocalID, ItemID); |
494 | } | 441 | } |
495 | 442 | ||
496 | public void RemoveState() | 443 | public void RemoveState() |
497 | { | 444 | { |
498 | string savedState = Path.Combine(Path.GetDirectoryName(m_Assembly), | 445 | string savedState = Path.Combine(Path.GetDirectoryName(m_Assembly), |
499 | m_ItemID.ToString() + ".state"); | 446 | ItemID.ToString() + ".state"); |
500 | 447 | ||
501 | try | 448 | try |
502 | { | 449 | { |
@@ -509,7 +456,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
509 | 456 | ||
510 | public void VarDump(Dictionary<string, object> vars) | 457 | public void VarDump(Dictionary<string, object> vars) |
511 | { | 458 | { |
512 | // m_log.Info("Variable dump for script "+ m_ItemID.ToString()); | 459 | // m_log.Info("Variable dump for script "+ ItemID.ToString()); |
513 | // foreach (KeyValuePair<string, object> v in vars) | 460 | // foreach (KeyValuePair<string, object> v in vars) |
514 | // { | 461 | // { |
515 | // m_log.Info("Variable: "+v.Key+" = "+v.Value.ToString()); | 462 | // m_log.Info("Variable: "+v.Key+" = "+v.Value.ToString()); |
@@ -518,17 +465,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
518 | 465 | ||
519 | public void Start() | 466 | public void Start() |
520 | { | 467 | { |
521 | lock (m_EventQueue) | 468 | lock (EventQueue) |
522 | { | 469 | { |
523 | if (Running) | 470 | if (Running) |
524 | return; | 471 | return; |
525 | 472 | ||
526 | m_RunEvents = true; | 473 | Running = true; |
474 | |||
475 | TimeStarted = DateTime.Now; | ||
476 | MeasurementPeriodTickStart = Util.EnvironmentTickCount(); | ||
477 | MeasurementPeriodExecutionTime = 0; | ||
527 | 478 | ||
528 | if (m_EventQueue.Count > 0) | 479 | if (EventQueue.Count > 0) |
529 | { | 480 | { |
530 | if (m_CurrentResult == null) | 481 | if (m_CurrentWorkItem == null) |
531 | m_CurrentResult = m_Engine.QueueEventHandler(this); | 482 | m_CurrentWorkItem = Engine.QueueEventHandler(this); |
532 | // else | 483 | // else |
533 | // m_log.Error("[Script] Tried to start a script that was already queued"); | 484 | // m_log.Error("[Script] Tried to start a script that was already queued"); |
534 | } | 485 | } |
@@ -538,51 +489,63 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
538 | public bool Stop(int timeout) | 489 | public bool Stop(int timeout) |
539 | { | 490 | { |
540 | // m_log.DebugFormat( | 491 | // m_log.DebugFormat( |
541 | // "[SCRIPT INSTANCE]: Stopping script {0} {1} with timeout {2}", ScriptName, ItemID, timeout); | 492 | // "[SCRIPT INSTANCE]: Stopping script {0} {1} in {2} {3} with timeout {4} {5} {6}", |
493 | // ScriptName, ItemID, PrimName, ObjectID, timeout, m_InSelfDelete, DateTime.Now.Ticks); | ||
542 | 494 | ||
543 | IScriptWorkItem result; | 495 | IScriptWorkItem workItem; |
544 | 496 | ||
545 | lock (m_EventQueue) | 497 | lock (EventQueue) |
546 | { | 498 | { |
547 | if (!Running) | 499 | if (!Running) |
548 | return true; | 500 | return true; |
549 | 501 | ||
550 | if (m_CurrentResult == null) | 502 | // If we're not running or waiting to run an event then we can safely stop. |
503 | if (m_CurrentWorkItem == null) | ||
551 | { | 504 | { |
552 | m_RunEvents = false; | 505 | Running = false; |
553 | return true; | 506 | return true; |
554 | } | 507 | } |
555 | 508 | ||
556 | if (m_CurrentResult.Cancel()) | 509 | // If we are waiting to run an event then we can try to cancel it. |
510 | if (m_CurrentWorkItem.Cancel()) | ||
557 | { | 511 | { |
558 | m_CurrentResult = null; | 512 | m_CurrentWorkItem = null; |
559 | m_RunEvents = false; | 513 | Running = false; |
560 | return true; | 514 | return true; |
561 | } | 515 | } |
562 | 516 | ||
563 | result = m_CurrentResult; | 517 | workItem = m_CurrentWorkItem; |
564 | m_RunEvents = false; | 518 | Running = false; |
565 | } | 519 | } |
566 | 520 | ||
567 | if (result.Wait(new TimeSpan((long)timeout * 100000))) | 521 | // Wait for the current event to complete. |
522 | if (!m_InSelfDelete && workItem.Wait(new TimeSpan((long)timeout * 100000))) | ||
568 | { | 523 | { |
569 | return true; | 524 | return true; |
570 | } | 525 | } |
571 | 526 | ||
572 | lock (m_EventQueue) | 527 | lock (EventQueue) |
573 | { | 528 | { |
574 | result = m_CurrentResult; | 529 | workItem = m_CurrentWorkItem; |
575 | } | 530 | } |
576 | 531 | ||
577 | if (result == null) | 532 | if (workItem == null) |
578 | return true; | 533 | return true; |
579 | 534 | ||
535 | // If the event still hasn't stopped and we the stop isn't the result of script or object removal, then | ||
536 | // forcibly abort the work item (this aborts the underlying thread). | ||
580 | if (!m_InSelfDelete) | 537 | if (!m_InSelfDelete) |
581 | result.Abort(); | 538 | { |
539 | // m_log.ErrorFormat( | ||
540 | // "[SCRIPT INSTANCE]: Aborting script {0} {1} in prim {2} {3} {4} {5}", | ||
541 | // ScriptName, ItemID, PrimName, ObjectID, m_InSelfDelete, DateTime.Now.Ticks); | ||
542 | |||
543 | workItem.Abort(); | ||
544 | } | ||
582 | 545 | ||
583 | lock (m_EventQueue) | 546 | lock (EventQueue) |
584 | { | 547 | { |
585 | m_CurrentResult = null; | 548 | m_CurrentWorkItem = null; |
586 | } | 549 | } |
587 | 550 | ||
588 | return true; | 551 | return true; |
@@ -603,10 +566,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
603 | throw new EventAbortException(); | 566 | throw new EventAbortException(); |
604 | } | 567 | } |
605 | 568 | ||
569 | /// <summary> | ||
570 | /// Post an event to this script instance. | ||
571 | /// </summary> | ||
572 | /// <remarks> | ||
573 | /// The request to run the event is sent | ||
574 | /// </remarks> | ||
575 | /// <param name="data"></param> | ||
606 | public void PostEvent(EventParams data) | 576 | public void PostEvent(EventParams data) |
607 | { | 577 | { |
608 | // m_log.DebugFormat("[Script] Posted event {2} in state {3} to {0}.{1}", | 578 | // m_log.DebugFormat("[Script] Posted event {2} in state {3} to {0}.{1}", |
609 | // m_PrimName, m_ScriptName, data.EventName, m_State); | 579 | // PrimName, ScriptName, data.EventName, State); |
610 | 580 | ||
611 | if (!Running) | 581 | if (!Running) |
612 | return; | 582 | return; |
@@ -621,9 +591,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
621 | m_nextEventTimeTicks = DateTime.Now.Ticks + m_eventDelayTicks; | 591 | m_nextEventTimeTicks = DateTime.Now.Ticks + m_eventDelayTicks; |
622 | } | 592 | } |
623 | 593 | ||
624 | lock (m_EventQueue) | 594 | lock (EventQueue) |
625 | { | 595 | { |
626 | if (m_EventQueue.Count >= m_MaxScriptQueue) | 596 | if (EventQueue.Count >= m_MaxScriptQueue) |
627 | return; | 597 | return; |
628 | 598 | ||
629 | if (data.EventName == "timer") | 599 | if (data.EventName == "timer") |
@@ -667,11 +637,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
667 | m_CollisionInQueue = true; | 637 | m_CollisionInQueue = true; |
668 | } | 638 | } |
669 | 639 | ||
670 | m_EventQueue.Enqueue(data); | 640 | EventQueue.Enqueue(data); |
671 | 641 | ||
672 | if (m_CurrentResult == null) | 642 | if (m_CurrentWorkItem == null) |
673 | { | 643 | { |
674 | m_CurrentResult = m_Engine.QueueEventHandler(this); | 644 | m_CurrentWorkItem = Engine.QueueEventHandler(this); |
675 | } | 645 | } |
676 | } | 646 | } |
677 | } | 647 | } |
@@ -682,6 +652,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
682 | /// <returns></returns> | 652 | /// <returns></returns> |
683 | public object EventProcessor() | 653 | public object EventProcessor() |
684 | { | 654 | { |
655 | // We check here as the thread stopping this instance from running may itself hold the m_Script lock. | ||
656 | if (!Running) | ||
657 | return 0; | ||
658 | |||
685 | lock (m_Script) | 659 | lock (m_Script) |
686 | { | 660 | { |
687 | // m_log.DebugFormat("[XEngine]: EventProcessor() invoked for {0}.{1}", PrimName, ScriptName); | 661 | // m_log.DebugFormat("[XEngine]: EventProcessor() invoked for {0}.{1}", PrimName, ScriptName); |
@@ -691,18 +665,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
691 | 665 | ||
692 | EventParams data = null; | 666 | EventParams data = null; |
693 | 667 | ||
694 | lock (m_EventQueue) | 668 | lock (EventQueue) |
695 | { | 669 | { |
696 | data = (EventParams) m_EventQueue.Dequeue(); | 670 | data = (EventParams)EventQueue.Dequeue(); |
697 | if (data == null) // Shouldn't happen | 671 | if (data == null) // Shouldn't happen |
698 | { | 672 | { |
699 | if ((m_EventQueue.Count > 0) && m_RunEvents && (!m_ShuttingDown)) | 673 | if (EventQueue.Count > 0 && Running && !ShuttingDown) |
700 | { | 674 | { |
701 | m_CurrentResult = m_Engine.QueueEventHandler(this); | 675 | m_CurrentWorkItem = Engine.QueueEventHandler(this); |
702 | } | 676 | } |
703 | else | 677 | else |
704 | { | 678 | { |
705 | m_CurrentResult = null; | 679 | m_CurrentWorkItem = null; |
706 | } | 680 | } |
707 | return 0; | 681 | return 0; |
708 | } | 682 | } |
@@ -725,28 +699,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
725 | if (data.EventName == "state") // Hardcoded state change | 699 | if (data.EventName == "state") // Hardcoded state change |
726 | { | 700 | { |
727 | // m_log.DebugFormat("[Script] Script {0}.{1} state set to {2}", | 701 | // m_log.DebugFormat("[Script] Script {0}.{1} state set to {2}", |
728 | // m_PrimName, m_ScriptName, data.Params[0].ToString()); | 702 | // PrimName, ScriptName, data.Params[0].ToString()); |
729 | m_State = data.Params[0].ToString(); | 703 | State = data.Params[0].ToString(); |
730 | AsyncCommandManager.RemoveScript(m_Engine, | 704 | AsyncCommandManager.RemoveScript(Engine, |
731 | m_LocalID, m_ItemID); | 705 | LocalID, ItemID); |
732 | 706 | ||
733 | SceneObjectPart part = m_Engine.World.GetSceneObjectPart( | 707 | SceneObjectPart part = Engine.World.GetSceneObjectPart( |
734 | m_LocalID); | 708 | LocalID); |
735 | if (part != null) | 709 | if (part != null) |
736 | { | 710 | { |
737 | part.SetScriptEvents(m_ItemID, | 711 | part.SetScriptEvents(ItemID, |
738 | (int)m_Script.GetStateEventFlags(State)); | 712 | (int)m_Script.GetStateEventFlags(State)); |
739 | } | 713 | } |
740 | } | 714 | } |
741 | else | 715 | else |
742 | { | 716 | { |
743 | if (m_Engine.World.PipeEventsForScript(m_LocalID) || | 717 | if (Engine.World.PipeEventsForScript(LocalID) || |
744 | data.EventName == "control") // Don't freeze avies! | 718 | data.EventName == "control") // Don't freeze avies! |
745 | { | 719 | { |
746 | SceneObjectPart part = m_Engine.World.GetSceneObjectPart( | 720 | SceneObjectPart part = Engine.World.GetSceneObjectPart( |
747 | m_LocalID); | 721 | LocalID); |
748 | // m_log.DebugFormat("[Script] Delivered event {2} in state {3} to {0}.{1}", | 722 | // m_log.DebugFormat("[Script] Delivered event {2} in state {3} to {0}.{1}", |
749 | // m_PrimName, m_ScriptName, data.EventName, m_State); | 723 | // PrimName, ScriptName, data.EventName, State); |
750 | 724 | ||
751 | try | 725 | try |
752 | { | 726 | { |
@@ -754,8 +728,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
754 | m_EventStart = DateTime.Now; | 728 | m_EventStart = DateTime.Now; |
755 | m_InEvent = true; | 729 | m_InEvent = true; |
756 | 730 | ||
731 | int start = Util.EnvironmentTickCount(); | ||
732 | |||
733 | // Reset the measurement period when we reach the end of the current one. | ||
734 | if (start - MeasurementPeriodTickStart > MaxMeasurementPeriod) | ||
735 | MeasurementPeriodTickStart = start; | ||
736 | |||
757 | m_Script.ExecuteEvent(State, data.EventName, data.Params); | 737 | m_Script.ExecuteEvent(State, data.EventName, data.Params); |
758 | 738 | ||
739 | MeasurementPeriodExecutionTime += Util.EnvironmentTickCount() - start; | ||
740 | |||
759 | m_InEvent = false; | 741 | m_InEvent = false; |
760 | m_CurrentEvent = String.Empty; | 742 | m_CurrentEvent = String.Empty; |
761 | 743 | ||
@@ -764,7 +746,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
764 | // This will be the very first event we deliver | 746 | // This will be the very first event we deliver |
765 | // (state_entry) in default state | 747 | // (state_entry) in default state |
766 | // | 748 | // |
767 | |||
768 | SaveState(m_Assembly); | 749 | SaveState(m_Assembly); |
769 | 750 | ||
770 | m_SaveState = false; | 751 | m_SaveState = false; |
@@ -788,7 +769,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
788 | 769 | ||
789 | if (text.Length > 1000) | 770 | if (text.Length > 1000) |
790 | text = text.Substring(0, 1000); | 771 | text = text.Substring(0, 1000); |
791 | m_Engine.World.SimChat(Utils.StringToBytes(text), | 772 | Engine.World.SimChat(Utils.StringToBytes(text), |
792 | ChatTypeEnum.DebugChannel, 2147483647, | 773 | ChatTypeEnum.DebugChannel, 2147483647, |
793 | part.AbsolutePosition, | 774 | part.AbsolutePosition, |
794 | part.Name, part.UUID, false); | 775 | part.Name, part.UUID, false); |
@@ -810,27 +791,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
810 | { | 791 | { |
811 | m_InSelfDelete = true; | 792 | m_InSelfDelete = true; |
812 | if (part != null) | 793 | if (part != null) |
813 | m_Engine.World.DeleteSceneObject(part.ParentGroup, false); | 794 | Engine.World.DeleteSceneObject(part.ParentGroup, false); |
814 | } | 795 | } |
815 | else if ((e is TargetInvocationException) && (e.InnerException is ScriptDeleteException)) | 796 | else if ((e is TargetInvocationException) && (e.InnerException is ScriptDeleteException)) |
816 | { | 797 | { |
817 | m_InSelfDelete = true; | 798 | m_InSelfDelete = true; |
818 | if (part != null) | 799 | if (part != null) |
819 | part.Inventory.RemoveInventoryItem(m_ItemID); | 800 | part.Inventory.RemoveInventoryItem(ItemID); |
820 | } | 801 | } |
821 | } | 802 | } |
822 | } | 803 | } |
823 | } | 804 | } |
824 | 805 | ||
825 | lock (m_EventQueue) | 806 | // If there are more events and we are currently running and not shutting down, then ask the |
807 | // script engine to run the next event. | ||
808 | lock (EventQueue) | ||
826 | { | 809 | { |
827 | if ((m_EventQueue.Count > 0) && m_RunEvents && (!m_ShuttingDown)) | 810 | if (EventQueue.Count > 0 && Running && !ShuttingDown) |
828 | { | 811 | { |
829 | m_CurrentResult = m_Engine.QueueEventHandler(this); | 812 | m_CurrentWorkItem = Engine.QueueEventHandler(this); |
830 | } | 813 | } |
831 | else | 814 | else |
832 | { | 815 | { |
833 | m_CurrentResult = null; | 816 | m_CurrentWorkItem = null; |
834 | } | 817 | } |
835 | } | 818 | } |
836 | 819 | ||
@@ -859,15 +842,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
859 | ReleaseControls(); | 842 | ReleaseControls(); |
860 | 843 | ||
861 | Stop(0); | 844 | Stop(0); |
862 | SceneObjectPart part=m_Engine.World.GetSceneObjectPart(m_LocalID); | 845 | SceneObjectPart part = Engine.World.GetSceneObjectPart(LocalID); |
863 | part.Inventory.GetInventoryItem(m_ItemID).PermsMask = 0; | 846 | part.Inventory.GetInventoryItem(ItemID).PermsMask = 0; |
864 | part.Inventory.GetInventoryItem(m_ItemID).PermsGranter = UUID.Zero; | 847 | part.Inventory.GetInventoryItem(ItemID).PermsGranter = UUID.Zero; |
865 | AsyncCommandManager.RemoveScript(m_Engine, m_LocalID, m_ItemID); | 848 | AsyncCommandManager.RemoveScript(Engine, LocalID, ItemID); |
866 | m_EventQueue.Clear(); | 849 | EventQueue.Clear(); |
867 | m_Script.ResetVars(); | 850 | m_Script.ResetVars(); |
868 | m_State = "default"; | 851 | State = "default"; |
869 | 852 | ||
870 | part.SetScriptEvents(m_ItemID, | 853 | part.SetScriptEvents(ItemID, |
871 | (int)m_Script.GetStateEventFlags(State)); | 854 | (int)m_Script.GetStateEventFlags(State)); |
872 | if (running) | 855 | if (running) |
873 | Start(); | 856 | Start(); |
@@ -884,16 +867,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
884 | ReleaseControls(); | 867 | ReleaseControls(); |
885 | 868 | ||
886 | m_Script.ResetVars(); | 869 | m_Script.ResetVars(); |
887 | SceneObjectPart part=m_Engine.World.GetSceneObjectPart(m_LocalID); | 870 | SceneObjectPart part = Engine.World.GetSceneObjectPart(LocalID); |
888 | part.Inventory.GetInventoryItem(m_ItemID).PermsMask = 0; | 871 | part.Inventory.GetInventoryItem(ItemID).PermsMask = 0; |
889 | part.Inventory.GetInventoryItem(m_ItemID).PermsGranter = UUID.Zero; | 872 | part.Inventory.GetInventoryItem(ItemID).PermsGranter = UUID.Zero; |
890 | AsyncCommandManager.RemoveScript(m_Engine, m_LocalID, m_ItemID); | 873 | AsyncCommandManager.RemoveScript(Engine, LocalID, ItemID); |
891 | 874 | ||
892 | m_EventQueue.Clear(); | 875 | EventQueue.Clear(); |
893 | m_Script.ResetVars(); | 876 | m_Script.ResetVars(); |
894 | m_State = "default"; | 877 | State = "default"; |
895 | 878 | ||
896 | part.SetScriptEvents(m_ItemID, | 879 | part.SetScriptEvents(ItemID, |
897 | (int)m_Script.GetStateEventFlags(State)); | 880 | (int)m_Script.GetStateEventFlags(State)); |
898 | 881 | ||
899 | if (m_CurrentEvent != "state_entry") | 882 | if (m_CurrentEvent != "state_entry") |
@@ -940,8 +923,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
940 | 923 | ||
941 | public void SaveState(string assembly) | 924 | public void SaveState(string assembly) |
942 | { | 925 | { |
943 | |||
944 | |||
945 | // If we're currently in an event, just tell it to save upon return | 926 | // If we're currently in an event, just tell it to save upon return |
946 | // | 927 | // |
947 | if (m_InEvent) | 928 | if (m_InEvent) |
@@ -950,7 +931,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
950 | return; | 931 | return; |
951 | } | 932 | } |
952 | 933 | ||
953 | PluginData = AsyncCommandManager.GetSerializationData(m_Engine, m_ItemID); | 934 | PluginData = AsyncCommandManager.GetSerializationData(Engine, ItemID); |
954 | 935 | ||
955 | string xml = ScriptSerializer.Serialize(this); | 936 | string xml = ScriptSerializer.Serialize(this); |
956 | 937 | ||
@@ -962,7 +943,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
962 | { | 943 | { |
963 | try | 944 | try |
964 | { | 945 | { |
965 | FileStream fs = File.Create(Path.Combine(Path.GetDirectoryName(assembly), m_ItemID.ToString() + ".state")); | 946 | FileStream fs = File.Create(Path.Combine(Path.GetDirectoryName(assembly), ItemID.ToString() + ".state")); |
966 | System.Text.UTF8Encoding enc = new System.Text.UTF8Encoding(); | 947 | System.Text.UTF8Encoding enc = new System.Text.UTF8Encoding(); |
967 | Byte[] buf = enc.GetBytes(xml); | 948 | Byte[] buf = enc.GetBytes(xml); |
968 | fs.Write(buf, 0, buf.Length); | 949 | fs.Write(buf, 0, buf.Length); |
@@ -972,7 +953,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
972 | { | 953 | { |
973 | // m_log.Error("Unable to save xml\n"+e.ToString()); | 954 | // m_log.Error("Unable to save xml\n"+e.ToString()); |
974 | } | 955 | } |
975 | //if (!File.Exists(Path.Combine(Path.GetDirectoryName(assembly), m_ItemID.ToString() + ".state"))) | 956 | //if (!File.Exists(Path.Combine(Path.GetDirectoryName(assembly), ItemID.ToString() + ".state"))) |
976 | //{ | 957 | //{ |
977 | // throw new Exception("Completed persistence save, but no file was created"); | 958 | // throw new Exception("Completed persistence save, but no file was created"); |
978 | //} | 959 | //} |
@@ -989,7 +970,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
989 | 970 | ||
990 | public override string ToString() | 971 | public override string ToString() |
991 | { | 972 | { |
992 | return String.Format("{0} {1} on {2}", m_ScriptName, m_ItemID, m_PrimName); | 973 | return String.Format("{0} {1} on {2}", ScriptName, ItemID, PrimName); |
993 | } | 974 | } |
994 | 975 | ||
995 | string FormatException(Exception e) | 976 | string FormatException(Exception e) |
@@ -1057,7 +1038,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
1057 | 1038 | ||
1058 | // Force an update of the in-memory plugin data | 1039 | // Force an update of the in-memory plugin data |
1059 | // | 1040 | // |
1060 | PluginData = AsyncCommandManager.GetSerializationData(m_Engine, m_ItemID); | 1041 | PluginData = AsyncCommandManager.GetSerializationData(Engine, ItemID); |
1061 | 1042 | ||
1062 | return ScriptSerializer.Serialize(this); | 1043 | return ScriptSerializer.Serialize(this); |
1063 | } | 1044 | } |