aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--OpenSim/Framework/Monitoring/Watchdog.cs39
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs68
2 files changed, 62 insertions, 45 deletions
diff --git a/OpenSim/Framework/Monitoring/Watchdog.cs b/OpenSim/Framework/Monitoring/Watchdog.cs
index ebbf095..0feec7c 100644
--- a/OpenSim/Framework/Monitoring/Watchdog.cs
+++ b/OpenSim/Framework/Monitoring/Watchdog.cs
@@ -454,7 +454,38 @@ namespace OpenSim.Framework.Monitoring
454 m_watchdogTimer.Start(); 454 m_watchdogTimer.Start();
455 } 455 }
456 456
457 public static void RunWhenPossible(string jobType, WaitCallback callback, string name, object obj, bool log = false) 457 /// <summary>
458 /// Run a job.
459 /// </summary>
460 /// <remarks>
461 /// This differs from direct scheduling (e.g. Util.FireAndForget) in that a job can be run in the job
462 /// engine if it is running, where all jobs are currently performed in sequence on a single thread. This is
463 /// to prevent observed overload and server freeze problems when there are hundreds of connections which all attempt to
464 /// perform work at once (e.g. in conference situations). With lower numbers of connections, the small
465 /// delay in performing jobs in sequence rather than concurrently has not been notiecable in testing, though a future more
466 /// sophisticated implementation could perform jobs concurrently when the server is under low load.
467 ///
468 /// However, be advised that some callers of this function rely on all jobs being performed in sequence if any
469 /// jobs are performed in sequence (i.e. if jobengine is active or not). Therefore, expanding the jobengine
470 /// beyond a single thread will require considerable thought.
471 ///
472 /// Also, any jobs submitted must be guaranteed to complete within a reasonable timeframe (e.g. they cannot
473 /// incorporate a network delay with a long timeout). At the moment, work that could suffer such issues
474 /// should still be run directly with RunInThread(), Util.FireAndForget(), etc. This is another area where
475 /// the job engine could be improved and so CPU utilization improved by better management of concurrency within
476 /// OpenSimulator.
477 /// </remarks>
478 /// <param name="jobType">General classification for the job (e.g. "RezAttachments").</param>
479 /// <param name="callback">Callback for job.</param>
480 /// <param name="name">Specific name of job (e.g. "RezAttachments for Joe Bloggs"</param>
481 /// <param name="obj">Object to pass to callback when run</param>
482 /// <param name="canRunInThisThread">If set to true then the job may be run in ths calling thread.</param>
483 /// <param name="mustNotTimeout">If the true then the job must never timeout.</param>
484 /// <param name="log">If set to true then extra logging is performed.</param>
485 public static void RunJob(
486 string jobType, WaitCallback callback, string name, object obj,
487 bool canRunInThisThread = false, bool mustNotTimeout = false,
488 bool log = false)
458 { 489 {
459 if (Util.FireAndForgetMethod == FireAndForgetMethod.RegressionTest) 490 if (Util.FireAndForgetMethod == FireAndForgetMethod.RegressionTest)
460 { 491 {
@@ -465,8 +496,12 @@ namespace OpenSim.Framework.Monitoring
465 496
466 if (JobEngine.IsRunning) 497 if (JobEngine.IsRunning)
467 JobEngine.QueueRequest(name, callback, obj); 498 JobEngine.QueueRequest(name, callback, obj);
468 else 499 else if (canRunInThisThread)
500 callback(obj);
501 else if (mustNotTimeout)
469 RunInThread(callback, name, obj, log); 502 RunInThread(callback, name, obj, log);
503 else
504 Util.FireAndForget(callback, obj, name);
470 } 505 }
471 } 506 }
472} \ No newline at end of file 507} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 1d234e2..757ec43 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -1228,15 +1228,11 @@ namespace OpenSim.Region.Framework.Scenes
1228 // viewers without (e.g. v1 viewers) will not, so we still need to make this call. 1228 // viewers without (e.g. v1 viewers) will not, so we still need to make this call.
1229 if (Scene.AttachmentsModule != null) 1229 if (Scene.AttachmentsModule != null)
1230 { 1230 {
1231 if (Watchdog.JobEngine.IsRunning) 1231 Watchdog.RunJob(
1232 Watchdog.RunWhenPossible( 1232 "RezAttachments",
1233 "RezAttachments", 1233 o => Scene.AttachmentsModule.RezAttachments(this),
1234 o => Scene.AttachmentsModule.RezAttachments(this), 1234 string.Format("Rez attachments for {0} in {1}", Name, Scene.Name),
1235 string.Format("Rez attachments for {0} in {1}", Name, Scene.Name), 1235 null);
1236 null);
1237 else
1238 Util.FireAndForget(
1239 o => Scene.AttachmentsModule.RezAttachments(this), null, "ScenePresence.RezAttachmentsOnLogin");
1240 } 1236 }
1241 } 1237 }
1242 else 1238 else
@@ -1258,18 +1254,12 @@ namespace OpenSim.Region.Framework.Scenes
1258 1254
1259 if (attachments.Count > 0) 1255 if (attachments.Count > 0)
1260 { 1256 {
1261 if (Watchdog.JobEngine.IsRunning) 1257 Watchdog.RunJob(
1262 { 1258 "StartAttachmentScripts",
1263 Watchdog.RunWhenPossible( 1259 o => RestartAttachmentScripts(attachments),
1264 "StartAttachmentScripts", 1260 string.Format("Start attachment scripts for {0} in {1}", Name, Scene.Name),
1265 o => RestartAttachmentScripts(attachments), 1261 null,
1266 string.Format("Start attachment scripts for {0} in {1}", Name, Scene.Name), 1262 true);
1267 null);
1268 }
1269 else
1270 {
1271 RestartAttachmentScripts(attachments);
1272 }
1273 } 1263 }
1274 } 1264 }
1275 1265
@@ -1825,18 +1815,12 @@ namespace OpenSim.Region.Framework.Scenes
1825 // XXX: If we force an update after activity has completed, then multiple attachments do appear correctly on a destination region 1815 // XXX: If we force an update after activity has completed, then multiple attachments do appear correctly on a destination region
1826 // If we do it a little bit earlier (e.g. when converting the child to a root agent) then this does not work. 1816 // If we do it a little bit earlier (e.g. when converting the child to a root agent) then this does not work.
1827 // This may be due to viewer code or it may be something we're not doing properly simulator side. 1817 // This may be due to viewer code or it may be something we're not doing properly simulator side.
1828 if (Watchdog.JobEngine.IsRunning) 1818 Watchdog.RunJob(
1829 { 1819 "ScheduleAttachmentsForFullUpdate",
1830 Watchdog.RunWhenPossible( 1820 o => ScheduleAttachmentsForFullUpdate(),
1831 "ScheduleAttachmentsForFullUpdate", 1821 string.Format("Schedule attachments for full update for {0} in {1}", Name, Scene.Name),
1832 o => ScheduleAttachmentsForFullUpdate(), 1822 null,
1833 string.Format("Schedule attachments for full update for {0} in {1}", Name, Scene.Name), 1823 true);
1834 null);
1835 }
1836 else
1837 {
1838 ScheduleAttachmentsForFullUpdate();
1839 }
1840 1824
1841 // m_log.DebugFormat( 1825 // m_log.DebugFormat(
1842 // "[SCENE PRESENCE]: Completing movement of {0} into region {1} took {2}ms", 1826 // "[SCENE PRESENCE]: Completing movement of {0} into region {1} took {2}ms",
@@ -3391,7 +3375,7 @@ namespace OpenSim.Region.Framework.Scenes
3391 SentInitialDataToClient = true; 3375 SentInitialDataToClient = true;
3392 3376
3393 // Send all scene object to the new client 3377 // Send all scene object to the new client
3394 Watchdog.RunWhenPossible("SendInitialDataToClient", delegate 3378 Watchdog.RunJob("SendInitialDataToClient", delegate
3395 { 3379 {
3396// m_log.DebugFormat( 3380// m_log.DebugFormat(
3397// "[SCENE PRESENCE]: Sending initial data to {0} agent {1} in {2}, tp flags {3}", 3381// "[SCENE PRESENCE]: Sending initial data to {0} agent {1} in {2}, tp flags {3}",
@@ -3409,7 +3393,7 @@ namespace OpenSim.Region.Framework.Scenes
3409 if (e != null && e is SceneObjectGroup) 3393 if (e != null && e is SceneObjectGroup)
3410 ((SceneObjectGroup)e).SendFullUpdateToClient(ControllingClient); 3394 ((SceneObjectGroup)e).SendFullUpdateToClient(ControllingClient);
3411 } 3395 }
3412 }, string.Format("SendInitialDataToClient ({0} in {1})", Name, Scene.Name), null); 3396 }, string.Format("SendInitialDataToClient ({0} in {1})", Name, Scene.Name),null, false, true);
3413 } 3397 }
3414 3398
3415 /// <summary> 3399 /// <summary>
@@ -4073,14 +4057,12 @@ namespace OpenSim.Region.Framework.Scenes
4073 // We don't need to worry about a race condition as the job to later start the scripts is also 4057 // We don't need to worry about a race condition as the job to later start the scripts is also
4074 // JobEngine scheduled and so will always occur after this task. 4058 // JobEngine scheduled and so will always occur after this task.
4075 // XXX: This will not be true if JobEngine ever gets more than one thread. 4059 // XXX: This will not be true if JobEngine ever gets more than one thread.
4076 if (Watchdog.JobEngine.IsRunning) 4060 Watchdog.RunJob(
4077 Watchdog.RunWhenPossible( 4061 "CopyAttachments",
4078 "CopyAttachments", 4062 o => Scene.AttachmentsModule.CopyAttachments(cAgent, this),
4079 o => Scene.AttachmentsModule.CopyAttachments(cAgent, this), 4063 string.Format("Copy attachments for {0} entering {1}", Name, Scene.Name),
4080 string.Format("Copy attachments for {0} entering {1}", Name, Scene.Name), 4064 null,
4081 null); 4065 true);
4082 else
4083 Scene.AttachmentsModule.CopyAttachments(cAgent, this);
4084 } 4066 }
4085 4067
4086 // This must occur after attachments are copied or scheduled to be copied, as it releases the CompleteMovement() calling thread 4068 // This must occur after attachments are copied or scheduled to be copied, as it releases the CompleteMovement() calling thread