aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs419
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 }