diff options
-rw-r--r-- | OpenSim/Framework/Monitoring/Watchdog.cs | 39 | ||||
-rw-r--r-- | OpenSim/Region/Framework/Scenes/ScenePresence.cs | 68 |
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 |