diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 34ad58af32..6e70c3609f 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -171,6 +171,11 @@ namespace OpenSim.Region.Framework.Scenes protected set; } + /// + /// Current maintenance run number + /// + public uint MaintenanceRun { get; private set; } + /// /// The minimum length of time in seconds that will be taken for a scene frame. If the frame takes less time then we /// will sleep for the remaining period. @@ -181,6 +186,11 @@ namespace OpenSim.Region.Framework.Scenes /// public float MinFrameTime { get; private set; } + /// + /// The minimum length of time in seconds that will be taken for a maintenance run. + /// + public float MinMaintenanceTime { get; private set; } + private int m_update_physics = 1; private int m_update_entitymovement = 1; private int m_update_objects = 1; @@ -209,6 +219,11 @@ namespace OpenSim.Region.Framework.Scenes private int m_lastFrameTick; public bool CombineRegions = false; + /// + /// Tick at which the last maintenance run occurred. + /// + private int m_lastMaintenanceTick; + /// /// Signals whether temporary objects are currently being cleaned up. Needed because this is launched /// asynchronously from the update loop. @@ -582,6 +597,7 @@ namespace OpenSim.Region.Framework.Scenes { m_config = config; MinFrameTime = 0.089f; + MinMaintenanceTime = 1; Random random = new Random(); @@ -1275,6 +1291,10 @@ namespace OpenSim.Region.Framework.Scenes // don't turn on the watchdog alarm for this thread until the second frame, in order to prevent false // alarms for scenes with many objects. Update(1); + + Watchdog.StartThread( + Maintenance, string.Format("Maintenance ({0})", RegionInfo.RegionName), ThreadPriority.Normal, false, true); + Watchdog.GetCurrentThreadInfo().AlarmIfTimeout = true; Update(-1); @@ -1290,6 +1310,63 @@ namespace OpenSim.Region.Framework.Scenes Watchdog.RemoveThread(); } + private void Maintenance() + { + DoMaintenance(-1); + + Watchdog.RemoveThread(); + } + + public void DoMaintenance(int runs) + { + long? endRun = null; + int runtc; + int previousMaintenanceTick; + + if (runs >= 0) + endRun = MaintenanceRun + runs; + + List coarseLocations; + List avatarUUIDs; + + while (!m_shuttingDown && (endRun == null || MaintenanceRun < endRun)) + { + runtc = Util.EnvironmentTickCount(); + ++MaintenanceRun; + + // Coarse locations relate to positions of green dots on the mini-map (on a SecondLife client) + if (MaintenanceRun % (m_update_coarse_locations / 10) == 0) + { + SceneGraph.GetCoarseLocations(out coarseLocations, out avatarUUIDs, 60); + // Send coarse locations to clients + ForEachScenePresence(delegate(ScenePresence presence) + { + presence.SendCoarseLocations(coarseLocations, avatarUUIDs); + }); + } + + Watchdog.UpdateThread(); + + previousMaintenanceTick = m_lastMaintenanceTick; + m_lastMaintenanceTick = Util.EnvironmentTickCount(); + runtc = Util.EnvironmentTickCountSubtract(m_lastMaintenanceTick, runtc); + runtc = (int)(MinMaintenanceTime * 1000) - runtc; + + if (runtc > 0) + Thread.Sleep(runtc); + + // Optionally warn if a frame takes double the amount of time that it should. + if (DebugUpdates + && Util.EnvironmentTickCountSubtract( + m_lastMaintenanceTick, previousMaintenanceTick) > (int)(MinMaintenanceTime * 1000 * 2)) + m_log.WarnFormat( + "[SCENE]: Maintenance took {0} ms (desired max {1} ms) in {2}", + Util.EnvironmentTickCountSubtract(m_lastMaintenanceTick, previousMaintenanceTick), + MinMaintenanceTime * 1000, + RegionInfo.RegionName); + } + } + public override void Update(int frames) { long? endFrame = null; @@ -1301,8 +1378,6 @@ namespace OpenSim.Region.Framework.Scenes int tmpPhysicsMS, tmpPhysicsMS2, tmpAgentMS, tmpTempOnRezMS, evMS, backMS, terMS; int previousFrameTick; int maintc; - List coarseLocations; - List avatarUUIDs; while (!m_shuttingDown && (endFrame == null || Frame < endFrame)) { @@ -1354,17 +1429,6 @@ namespace OpenSim.Region.Framework.Scenes if (Frame % m_update_presences == 0) m_sceneGraph.UpdatePresences(); - // Coarse locations relate to positions of green dots on the mini-map (on a SecondLife client) - if (Frame % m_update_coarse_locations == 0) - { - SceneGraph.GetCoarseLocations(out coarseLocations, out avatarUUIDs, 60); - // Send coarse locations to clients - ForEachScenePresence(delegate(ScenePresence presence) - { - presence.SendCoarseLocations(coarseLocations, avatarUUIDs); - }); - } - agentMS += Util.EnvironmentTickCountSubtract(tmpAgentMS); // Delete temp-on-rez stuff @@ -1472,7 +1536,6 @@ namespace OpenSim.Region.Framework.Scenes EventManager.TriggerRegionHeartbeatEnd(this); - // Tell the watchdog that this thread is still alive Watchdog.UpdateThread(); previousFrameTick = m_lastFrameTick;