diff options
Diffstat (limited to '')
4 files changed, 113 insertions, 67 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/MockScene.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/MockScene.cs index e2178e5..39d1875 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/MockScene.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/MockScene.cs | |||
@@ -49,7 +49,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests | |||
49 | m_regStatus = RegionStatus.Up; | 49 | m_regStatus = RegionStatus.Up; |
50 | } | 50 | } |
51 | 51 | ||
52 | public override void Update(int frames) {} | 52 | public override bool Update(int frames) { return true; } |
53 | public override void LoadWorldMap() {} | 53 | public override void LoadWorldMap() {} |
54 | 54 | ||
55 | public override ISceneAgent AddNewAgent(IClientAPI client, PresenceType type) | 55 | public override ISceneAgent AddNewAgent(IClientAPI client, PresenceType type) |
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index a43de29..53001e9 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs | |||
@@ -329,6 +329,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
329 | private Dictionary<string, string> m_extraSettings; | 329 | private Dictionary<string, string> m_extraSettings; |
330 | 330 | ||
331 | /// <summary> | 331 | /// <summary> |
332 | /// If true then the next time the scene loop is activated, updates will be performed by firing of a timer | ||
333 | /// rather than on a single thread that sleeps. | ||
334 | /// </summary> | ||
335 | public bool UpdateOnTimer { get; set; } | ||
336 | |||
337 | /// <summary> | ||
338 | /// Only used if we are updating scene on a timer rather than sleeping a thread. | ||
339 | /// </summary> | ||
340 | private Timer m_sceneUpdateTimer; | ||
341 | |||
342 | /// <summary> | ||
332 | /// Current scene frame number | 343 | /// Current scene frame number |
333 | /// </summary> | 344 | /// </summary> |
334 | public uint Frame | 345 | public uint Frame |
@@ -430,7 +441,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
430 | /// Is the scene active? | 441 | /// Is the scene active? |
431 | /// </summary> | 442 | /// </summary> |
432 | /// <remarks> | 443 | /// <remarks> |
433 | /// If false, maintenance and update loops are not being run. Updates can still be triggered manually if | 444 | /// If false, maintenance and update loops are not being run, though after setting to false update may still |
445 | /// be active for a period (and IsRunning will still be true). Updates can still be triggered manually if | ||
434 | /// the scene is not active. | 446 | /// the scene is not active. |
435 | /// </remarks> | 447 | /// </remarks> |
436 | public bool Active | 448 | public bool Active |
@@ -453,8 +465,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
453 | } | 465 | } |
454 | private volatile bool m_active; | 466 | private volatile bool m_active; |
455 | 467 | ||
456 | // private int m_lastUpdate; | 468 | /// <summary> |
457 | // private bool m_firstHeartbeat = true; | 469 | /// If true then updates are running. This may be true for a short period after a scene is de-activated. |
470 | /// </summary> | ||
471 | public bool IsRunning { get { return m_isRunning; } } | ||
472 | private volatile bool m_isRunning; | ||
458 | 473 | ||
459 | private Timer m_mapGenerationTimer = new Timer(); | 474 | private Timer m_mapGenerationTimer = new Timer(); |
460 | private bool m_generateMaptiles; | 475 | private bool m_generateMaptiles; |
@@ -1352,19 +1367,18 @@ namespace OpenSim.Region.Framework.Scenes | |||
1352 | /// </param> | 1367 | /// </param> |
1353 | public void Start(bool startScripts) | 1368 | public void Start(bool startScripts) |
1354 | { | 1369 | { |
1370 | if (IsRunning) | ||
1371 | return; | ||
1372 | |||
1373 | m_isRunning = true; | ||
1355 | m_active = true; | 1374 | m_active = true; |
1356 | 1375 | ||
1357 | // m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName); | 1376 | // m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName); |
1358 | |||
1359 | //m_heartbeatTimer.Enabled = true; | ||
1360 | //m_heartbeatTimer.Interval = (int)(m_timespan * 1000); | ||
1361 | //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat); | ||
1362 | if (m_heartbeatThread != null) | 1377 | if (m_heartbeatThread != null) |
1363 | { | 1378 | { |
1364 | m_heartbeatThread.Abort(); | 1379 | m_heartbeatThread.Abort(); |
1365 | m_heartbeatThread = null; | 1380 | m_heartbeatThread = null; |
1366 | } | 1381 | } |
1367 | // m_lastUpdate = Util.EnvironmentTickCount(); | ||
1368 | 1382 | ||
1369 | m_heartbeatThread | 1383 | m_heartbeatThread |
1370 | = Watchdog.StartThread( | 1384 | = Watchdog.StartThread( |
@@ -1401,15 +1415,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
1401 | /// </summary> | 1415 | /// </summary> |
1402 | private void Heartbeat() | 1416 | private void Heartbeat() |
1403 | { | 1417 | { |
1404 | // if (!Monitor.TryEnter(m_heartbeatLock)) | ||
1405 | // { | ||
1406 | // Watchdog.RemoveThread(); | ||
1407 | // return; | ||
1408 | // } | ||
1409 | |||
1410 | // try | ||
1411 | // { | ||
1412 | |||
1413 | m_eventManager.TriggerOnRegionStarted(this); | 1418 | m_eventManager.TriggerOnRegionStarted(this); |
1414 | 1419 | ||
1415 | // The first frame can take a very long time due to physics actors being added on startup. Therefore, | 1420 | // The first frame can take a very long time due to physics actors being added on startup. Therefore, |
@@ -1418,21 +1423,37 @@ namespace OpenSim.Region.Framework.Scenes | |||
1418 | Update(1); | 1423 | Update(1); |
1419 | 1424 | ||
1420 | Watchdog.StartThread( | 1425 | Watchdog.StartThread( |
1421 | Maintenance, string.Format("Maintenance ({0})", RegionInfo.RegionName), ThreadPriority.Normal, false, true); | 1426 | Maintenance, string.Format("Maintenance ({0})", RegionInfo.RegionName), ThreadPriority.Normal, false, true); |
1422 | 1427 | ||
1423 | Watchdog.GetCurrentThreadInfo().AlarmIfTimeout = true; | 1428 | Watchdog.GetCurrentThreadInfo().AlarmIfTimeout = true; |
1424 | Update(-1); | ||
1425 | 1429 | ||
1426 | // m_lastUpdate = Util.EnvironmentTickCount(); | 1430 | if (UpdateOnTimer) |
1427 | // m_firstHeartbeat = false; | 1431 | { |
1428 | // } | 1432 | m_sceneUpdateTimer = new Timer(MinFrameTime * 1000); |
1429 | // finally | 1433 | m_sceneUpdateTimer.AutoReset = true; |
1430 | // { | 1434 | m_sceneUpdateTimer.Elapsed += Update; |
1431 | // Monitor.Pulse(m_heartbeatLock); | 1435 | m_sceneUpdateTimer.Start(); |
1432 | // Monitor.Exit(m_heartbeatLock); | 1436 | } |
1433 | // } | 1437 | else |
1438 | { | ||
1439 | Update(-1); | ||
1440 | Watchdog.RemoveThread(); | ||
1441 | m_isRunning = false; | ||
1442 | } | ||
1443 | } | ||
1434 | 1444 | ||
1435 | Watchdog.RemoveThread(); | 1445 | private void Update(object sender, ElapsedEventArgs e) |
1446 | { | ||
1447 | // If the last frame did not complete on time, then immediately start the next update on the same thread | ||
1448 | // and ignore further timed updates until we have a frame that had spare time. | ||
1449 | while (!Update(1) && Active) {} | ||
1450 | |||
1451 | if (!Active || m_shuttingDown) | ||
1452 | { | ||
1453 | m_sceneUpdateTimer.Stop(); | ||
1454 | m_sceneUpdateTimer = null; | ||
1455 | m_isRunning = false; | ||
1456 | } | ||
1436 | } | 1457 | } |
1437 | 1458 | ||
1438 | private void Maintenance() | 1459 | private void Maintenance() |
@@ -1502,7 +1523,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1502 | } | 1523 | } |
1503 | } | 1524 | } |
1504 | 1525 | ||
1505 | public override void Update(int frames) | 1526 | public override bool Update(int frames) |
1506 | { | 1527 | { |
1507 | long? endFrame = null; | 1528 | long? endFrame = null; |
1508 | 1529 | ||
@@ -1652,7 +1673,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
1652 | 1673 | ||
1653 | EventManager.TriggerRegionHeartbeatEnd(this); | 1674 | EventManager.TriggerRegionHeartbeatEnd(this); |
1654 | 1675 | ||
1655 | Watchdog.UpdateThread(); | 1676 | if (!UpdateOnTimer) |
1677 | Watchdog.UpdateThread(); | ||
1656 | 1678 | ||
1657 | previousFrameTick = m_lastFrameTick; | 1679 | previousFrameTick = m_lastFrameTick; |
1658 | m_lastFrameTick = Util.EnvironmentTickCount(); | 1680 | m_lastFrameTick = Util.EnvironmentTickCount(); |
@@ -1661,9 +1683,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
1661 | 1683 | ||
1662 | if (tmpMS > 0) | 1684 | if (tmpMS > 0) |
1663 | { | 1685 | { |
1664 | Thread.Sleep(tmpMS); | 1686 | spareMS = tmpMS; |
1665 | spareMS += tmpMS; | 1687 | |
1666 | } | 1688 | if (!UpdateOnTimer) |
1689 | Thread.Sleep(tmpMS); | ||
1690 | } | ||
1667 | 1691 | ||
1668 | frameMS = Util.EnvironmentTickCountSubtract(maintc); | 1692 | frameMS = Util.EnvironmentTickCountSubtract(maintc); |
1669 | maintc = Util.EnvironmentTickCount(); | 1693 | maintc = Util.EnvironmentTickCount(); |
@@ -1683,7 +1707,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1683 | StatsReporter.AddSpareMS(spareMS); | 1707 | StatsReporter.AddSpareMS(spareMS); |
1684 | StatsReporter.addScriptLines(m_sceneGraph.GetScriptLPS()); | 1708 | StatsReporter.addScriptLines(m_sceneGraph.GetScriptLPS()); |
1685 | 1709 | ||
1686 | // Optionally warn if a frame takes double the amount of time that it should. | 1710 | // Optionally warn if a frame takes double the amount of time that it should. |
1687 | if (DebugUpdates | 1711 | if (DebugUpdates |
1688 | && Util.EnvironmentTickCountSubtract( | 1712 | && Util.EnvironmentTickCountSubtract( |
1689 | m_lastFrameTick, previousFrameTick) > (int)(MinFrameTime * 1000 * 2)) | 1713 | m_lastFrameTick, previousFrameTick) > (int)(MinFrameTime * 1000 * 2)) |
@@ -1693,6 +1717,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
1693 | MinFrameTime * 1000, | 1717 | MinFrameTime * 1000, |
1694 | RegionInfo.RegionName); | 1718 | RegionInfo.RegionName); |
1695 | } | 1719 | } |
1720 | |||
1721 | return spareMS >= 0; | ||
1696 | } | 1722 | } |
1697 | 1723 | ||
1698 | public void AddGroupTarget(SceneObjectGroup grp) | 1724 | public void AddGroupTarget(SceneObjectGroup grp) |
diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs index 0445268..aaddce6 100644 --- a/OpenSim/Region/Framework/Scenes/SceneBase.cs +++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs | |||
@@ -196,7 +196,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
196 | /// Number of frames to update. Exits on shutdown even if there are frames remaining. | 196 | /// Number of frames to update. Exits on shutdown even if there are frames remaining. |
197 | /// If -1 then updates until shutdown. | 197 | /// If -1 then updates until shutdown. |
198 | /// </param> | 198 | /// </param> |
199 | public abstract void Update(int frames); | 199 | /// <returns>true if update completed within minimum frame time, false otherwise.</returns> |
200 | public abstract bool Update(int frames); | ||
200 | 201 | ||
201 | #endregion | 202 | #endregion |
202 | 203 | ||
diff --git a/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs b/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs index f2595c8..0927c4f 100644 --- a/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs +++ b/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs | |||
@@ -30,6 +30,7 @@ using System.Collections.Generic; | |||
30 | using System.Linq; | 30 | using System.Linq; |
31 | using System.Reflection; | 31 | using System.Reflection; |
32 | using System.Text; | 32 | using System.Text; |
33 | using System.Threading; | ||
33 | using log4net; | 34 | using log4net; |
34 | using Mono.Addins; | 35 | using Mono.Addins; |
35 | using Nini.Config; | 36 | using Nini.Config; |
@@ -93,42 +94,44 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments | |||
93 | "Debug", this, "debug scene get", | 94 | "Debug", this, "debug scene get", |
94 | "debug scene get", | 95 | "debug scene get", |
95 | "List current scene options.", | 96 | "List current scene options.", |
96 | "active - if false then main scene update and maintenance loops are suspended.\n" | 97 | "active - if false then main scene update and maintenance loops are suspended.\n" |
97 | + "animations - if true then extra animations debug information is logged.\n" | 98 | + "animations - if true then extra animations debug information is logged.\n" |
98 | + "appear-refresh - if true then appearance is resent to other avatars every 60 seconds.\n" | 99 | + "appear-refresh - if true then appearance is resent to other avatars every 60 seconds.\n" |
99 | + "child-repri - how far an avatar must move in meters before we update the position of its child agents in neighbouring regions.\n" | 100 | + "child-repri - how far an avatar must move in meters before we update the position of its child agents in neighbouring regions.\n" |
100 | + "client-pos-upd - the tolerance before clients are updated with new rotation information for an avatar.\n" | 101 | + "client-pos-upd - the tolerance before clients are updated with new rotation information for an avatar.\n" |
101 | + "client-rot-upd - the tolerance before clients are updated with new rotation information for an avatar.\n" | 102 | + "client-rot-upd - the tolerance before clients are updated with new rotation information for an avatar.\n" |
102 | + "client-vel-upd - the tolerance before clients are updated with new velocity information for an avatar.\n" | 103 | + "client-vel-upd - the tolerance before clients are updated with new velocity information for an avatar.\n" |
103 | + "root-upd-per - if greater than 1, terse updates are only sent to root agents other than the originator on every n updates.\n" | 104 | + "root-upd-per - if greater than 1, terse updates are only sent to root agents other than the originator on every n updates.\n" |
104 | + "child-upd-per - if greater than 1, terse updates are only sent to child agents on every n updates.\n" | 105 | + "child-upd-per - if greater than 1, terse updates are only sent to child agents on every n updates.\n" |
105 | + "collisions - if false then collisions with other objects are turned off.\n" | 106 | + "collisions - if false then collisions with other objects are turned off.\n" |
106 | + "pbackup - if false then periodic scene backup is turned off.\n" | 107 | + "pbackup - if false then periodic scene backup is turned off.\n" |
107 | + "physics - if false then all physics objects are non-physical.\n" | 108 | + "physics - if false then all physics objects are non-physical.\n" |
108 | + "scripting - if false then no scripting operations happen.\n" | 109 | + "scripting - if false then no scripting operations happen.\n" |
109 | + "teleport - if true then some extra teleport debug information is logged.\n" | 110 | + "teleport - if true then some extra teleport debug information is logged.\n" |
110 | + "updates - if true then any frame which exceeds double the maximum desired frame time is logged.", | 111 | + "update-on-timer - If true then the scene is updated via a timer. If false then a thread with sleep is used.\n" |
112 | + "updates - if true then any frame which exceeds double the maximum desired frame time is logged.", | ||
111 | HandleDebugSceneGetCommand); | 113 | HandleDebugSceneGetCommand); |
112 | 114 | ||
113 | scene.AddCommand( | 115 | scene.AddCommand( |
114 | "Debug", this, "debug scene set", | 116 | "Debug", this, "debug scene set", |
115 | "debug scene set active|collisions|pbackup|physics|scripting|teleport|updates true|false", | 117 | "debug scene set <param> <value>", |
116 | "Turn on scene debugging options.", | 118 | "Turn on scene debugging options.", |
117 | "active - if false then main scene update and maintenance loops are suspended.\n" | 119 | "active - if false then main scene update and maintenance loops are suspended.\n" |
118 | + "animations - if true then extra animations debug information is logged.\n" | 120 | + "animations - if true then extra animations debug information is logged.\n" |
119 | + "appear-refresh - if true then appearance is resent to other avatars every 60 seconds.\n" | 121 | + "appear-refresh - if true then appearance is resent to other avatars every 60 seconds.\n" |
120 | + "child-repri - how far an avatar must move in meters before we update the position of its child agents in neighbouring regions.\n" | 122 | + "child-repri - how far an avatar must move in meters before we update the position of its child agents in neighbouring regions.\n" |
121 | + "client-pos-upd - the tolerance before clients are updated with new rotation information for an avatar.\n" | 123 | + "client-pos-upd - the tolerance before clients are updated with new rotation information for an avatar.\n" |
122 | + "client-rot-upd - the tolerance before clients are updated with new rotation information for an avatar.\n" | 124 | + "client-rot-upd - the tolerance before clients are updated with new rotation information for an avatar.\n" |
123 | + "client-vel-upd - the tolerance before clients are updated with new velocity information for an avatar.\n" | 125 | + "client-vel-upd - the tolerance before clients are updated with new velocity information for an avatar.\n" |
124 | + "root-upd-per - if greater than 1, terse updates are only sent to root agents other than the originator on every n updates.\n" | 126 | + "root-upd-per - if greater than 1, terse updates are only sent to root agents other than the originator on every n updates.\n" |
125 | + "child-upd-per - if greater than 1, terse updates are only sent to child agents on every n updates.\n" | 127 | + "child-upd-per - if greater than 1, terse updates are only sent to child agents on every n updates.\n" |
126 | + "collisions - if false then collisions with other objects are turned off.\n" | 128 | + "collisions - if false then collisions with other objects are turned off.\n" |
127 | + "pbackup - if false then periodic scene backup is turned off.\n" | 129 | + "pbackup - if false then periodic scene backup is turned off.\n" |
128 | + "physics - if false then all physics objects are non-physical.\n" | 130 | + "physics - if false then all physics objects are non-physical.\n" |
129 | + "scripting - if false then no scripting operations happen.\n" | 131 | + "scripting - if false then no scripting operations happen.\n" |
130 | + "teleport - if true then some extra teleport debug information is logged.\n" | 132 | + "teleport - if true then some extra teleport debug information is logged.\n" |
131 | + "updates - if true then any frame which exceeds double the maximum desired frame time is logged.", | 133 | + "update-on-timer - If true then the scene is updated via a timer. If false then a thread with sleep is used.\n" |
134 | + "updates - if true then any frame which exceeds double the maximum desired frame time is logged.", | ||
132 | HandleDebugSceneSetCommand); | 135 | HandleDebugSceneSetCommand); |
133 | } | 136 | } |
134 | 137 | ||
@@ -163,6 +166,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments | |||
163 | cdl.AddRow("physics", m_scene.PhysicsEnabled); | 166 | cdl.AddRow("physics", m_scene.PhysicsEnabled); |
164 | cdl.AddRow("scripting", m_scene.ScriptsEnabled); | 167 | cdl.AddRow("scripting", m_scene.ScriptsEnabled); |
165 | cdl.AddRow("teleport", m_scene.DebugTeleporting); | 168 | cdl.AddRow("teleport", m_scene.DebugTeleporting); |
169 | cdl.AddRow("update-on-timer", m_scene.UpdateOnTimer); | ||
166 | cdl.AddRow("updates", m_scene.DebugUpdates); | 170 | cdl.AddRow("updates", m_scene.DebugUpdates); |
167 | 171 | ||
168 | MainConsole.Instance.OutputFormat("Scene {0} options:", m_scene.Name); | 172 | MainConsole.Instance.OutputFormat("Scene {0} options:", m_scene.Name); |
@@ -304,6 +308,21 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments | |||
304 | m_scene.DebugTeleporting = enableTeleportDebugging; | 308 | m_scene.DebugTeleporting = enableTeleportDebugging; |
305 | } | 309 | } |
306 | 310 | ||
311 | if (options.ContainsKey("update-on-timer")) | ||
312 | { | ||
313 | bool enableUpdateOnTimer; | ||
314 | if (bool.TryParse(options["update-on-timer"], out enableUpdateOnTimer)) | ||
315 | { | ||
316 | m_scene.UpdateOnTimer = enableUpdateOnTimer; | ||
317 | m_scene.Active = false; | ||
318 | |||
319 | while (m_scene.IsRunning) | ||
320 | Thread.Sleep(20); | ||
321 | |||
322 | m_scene.Active = true; | ||
323 | } | ||
324 | } | ||
325 | |||
307 | if (options.ContainsKey("updates")) | 326 | if (options.ContainsKey("updates")) |
308 | { | 327 | { |
309 | bool enableUpdateDebugging; | 328 | bool enableUpdateDebugging; |