diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 02a0268e36..e0af2d6709 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -129,7 +129,16 @@ namespace OpenSim.Region.Framework.Scenes
protected ICapabilitiesModule m_capsModule;
// Central Update Loop
protected int m_fps = 10;
- protected uint m_frame;
+
+ ///
+ /// Current scene frame number
+ ///
+ public uint Frame
+ {
+ get;
+ protected set;
+ }
+
protected float m_timespan = 0.089f;
protected DateTime m_lastupdate = DateTime.UtcNow;
@@ -1183,7 +1192,8 @@ namespace OpenSim.Region.Framework.Scenes
try
{
- Update();
+ while (!shuttingdown)
+ Update();
m_lastUpdate = Util.EnvironmentTickCount();
m_firstHeartbeat = false;
@@ -1200,187 +1210,176 @@ namespace OpenSim.Region.Framework.Scenes
Watchdog.RemoveThread();
}
- ///
- /// Performs per-frame updates on the scene, this should be the central scene loop
- ///
public override void Update()
- {
- float physicsFPS;
- int maintc;
+ {
+ TimeSpan SinceLastFrame = DateTime.UtcNow - m_lastupdate;
+ float physicsFPS = 0f;
- while (!shuttingdown)
+ int maintc = Util.EnvironmentTickCount();
+ int tmpFrameMS = maintc;
+ tempOnRezMS = eventMS = backupMS = terrainMS = landMS = 0;
+
+ // Increment the frame counter
+ ++Frame;
+
+ try
{
- TimeSpan SinceLastFrame = DateTime.UtcNow - m_lastupdate;
- physicsFPS = 0f;
+ // Check if any objects have reached their targets
+ CheckAtTargets();
- maintc = Util.EnvironmentTickCount();
- int tmpFrameMS = maintc;
- tempOnRezMS = eventMS = backupMS = terrainMS = landMS = 0;
+ // Update SceneObjectGroups that have scheduled themselves for updates
+ // Objects queue their updates onto all scene presences
+ if (Frame % m_update_objects == 0)
+ m_sceneGraph.UpdateObjectGroups();
- // Increment the frame counter
- ++m_frame;
+ // Run through all ScenePresences looking for updates
+ // Presence updates and queued object updates for each presence are sent to clients
+ if (Frame % m_update_presences == 0)
+ m_sceneGraph.UpdatePresences();
- try
+ // Coarse locations relate to positions of green dots on the mini-map (on a SecondLife client)
+ if (Frame % m_update_coarse_locations == 0)
{
- // Check if any objects have reached their targets
- CheckAtTargets();
-
- // Update SceneObjectGroups that have scheduled themselves for updates
- // Objects queue their updates onto all scene presences
- if (m_frame % m_update_objects == 0)
- m_sceneGraph.UpdateObjectGroups();
-
- // Run through all ScenePresences looking for updates
- // Presence updates and queued object updates for each presence are sent to clients
- if (m_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 (m_frame % m_update_coarse_locations == 0)
+ List coarseLocations;
+ List avatarUUIDs;
+ SceneGraph.GetCoarseLocations(out coarseLocations, out avatarUUIDs, 60);
+ // Send coarse locations to clients
+ ForEachScenePresence(delegate(ScenePresence presence)
{
- List coarseLocations;
- List avatarUUIDs;
- SceneGraph.GetCoarseLocations(out coarseLocations, out avatarUUIDs, 60);
- // Send coarse locations to clients
- ForEachScenePresence(delegate(ScenePresence presence)
- {
- presence.SendCoarseLocations(coarseLocations, avatarUUIDs);
- });
+ presence.SendCoarseLocations(coarseLocations, avatarUUIDs);
+ });
+ }
+
+ int tmpPhysicsMS2 = Util.EnvironmentTickCount();
+ if ((Frame % m_update_physics == 0) && m_physics_enabled)
+ m_sceneGraph.UpdatePreparePhysics();
+ physicsMS2 = Util.EnvironmentTickCountSubtract(tmpPhysicsMS2);
+
+ // Apply any pending avatar force input to the avatar's velocity
+ if (Frame % m_update_entitymovement == 0)
+ m_sceneGraph.UpdateScenePresenceMovement();
+
+ // Perform the main physics update. This will do the actual work of moving objects and avatars according to their
+ // velocity
+ int tmpPhysicsMS = Util.EnvironmentTickCount();
+ if (Frame % m_update_physics == 0)
+ {
+ if (m_physics_enabled)
+ physicsFPS = m_sceneGraph.UpdatePhysics(Math.Max(SinceLastFrame.TotalSeconds, m_timespan));
+ if (SynchronizeScene != null)
+ SynchronizeScene(this);
+ }
+ physicsMS = Util.EnvironmentTickCountSubtract(tmpPhysicsMS);
+
+ // Delete temp-on-rez stuff
+ if (Frame % 1000 == 0 && !m_cleaningTemps)
+ {
+ int tmpTempOnRezMS = Util.EnvironmentTickCount();
+ m_cleaningTemps = true;
+ Util.FireAndForget(delegate { CleanTempObjects(); m_cleaningTemps = false; });
+ tempOnRezMS = Util.EnvironmentTickCountSubtract(tmpTempOnRezMS);
+ }
+
+ if (RegionStatus != RegionStatus.SlaveScene)
+ {
+ if (Frame % m_update_events == 0)
+ {
+ int evMS = Util.EnvironmentTickCount();
+ UpdateEvents();
+ eventMS = Util.EnvironmentTickCountSubtract(evMS); ;
}
- int tmpPhysicsMS2 = Util.EnvironmentTickCount();
- if ((m_frame % m_update_physics == 0) && m_physics_enabled)
- m_sceneGraph.UpdatePreparePhysics();
- physicsMS2 = Util.EnvironmentTickCountSubtract(tmpPhysicsMS2);
-
- // Apply any pending avatar force input to the avatar's velocity
- if (m_frame % m_update_entitymovement == 0)
- m_sceneGraph.UpdateScenePresenceMovement();
-
- // Perform the main physics update. This will do the actual work of moving objects and avatars according to their
- // velocity
- int tmpPhysicsMS = Util.EnvironmentTickCount();
- if (m_frame % m_update_physics == 0)
+ if (Frame % m_update_backup == 0)
{
- if (m_physics_enabled)
- physicsFPS = m_sceneGraph.UpdatePhysics(Math.Max(SinceLastFrame.TotalSeconds, m_timespan));
- if (SynchronizeScene != null)
- SynchronizeScene(this);
- }
- physicsMS = Util.EnvironmentTickCountSubtract(tmpPhysicsMS);
-
- // Delete temp-on-rez stuff
- if (m_frame % 1000 == 0 && !m_cleaningTemps)
- {
- int tmpTempOnRezMS = Util.EnvironmentTickCount();
- m_cleaningTemps = true;
- Util.FireAndForget(delegate { CleanTempObjects(); m_cleaningTemps = false; });
- tempOnRezMS = Util.EnvironmentTickCountSubtract(tmpTempOnRezMS);
+ int backMS = Util.EnvironmentTickCount();
+ UpdateStorageBackup();
+ backupMS = Util.EnvironmentTickCountSubtract(backMS);
}
- if (RegionStatus != RegionStatus.SlaveScene)
+ if (Frame % m_update_terrain == 0)
{
- if (m_frame % m_update_events == 0)
- {
- int evMS = Util.EnvironmentTickCount();
- UpdateEvents();
- eventMS = Util.EnvironmentTickCountSubtract(evMS); ;
- }
-
- if (m_frame % m_update_backup == 0)
- {
- int backMS = Util.EnvironmentTickCount();
- UpdateStorageBackup();
- backupMS = Util.EnvironmentTickCountSubtract(backMS);
- }
-
- if (m_frame % m_update_terrain == 0)
- {
- int terMS = Util.EnvironmentTickCount();
- UpdateTerrain();
- terrainMS = Util.EnvironmentTickCountSubtract(terMS);
- }
-
- //if (m_frame % m_update_land == 0)
- //{
- // int ldMS = Util.EnvironmentTickCount();
- // UpdateLand();
- // landMS = Util.EnvironmentTickCountSubtract(ldMS);
- //}
-
- frameMS = Util.EnvironmentTickCountSubtract(tmpFrameMS);
- otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS;
- lastCompletedFrame = Util.EnvironmentTickCount();
-
- // if (m_frame%m_update_avatars == 0)
- // UpdateInWorldTime();
- StatsReporter.AddPhysicsFPS(physicsFPS);
- StatsReporter.AddTimeDilation(TimeDilation);
- StatsReporter.AddFPS(1);
- StatsReporter.SetRootAgents(m_sceneGraph.GetRootAgentCount());
- StatsReporter.SetChildAgents(m_sceneGraph.GetChildAgentCount());
- StatsReporter.SetObjects(m_sceneGraph.GetTotalObjectsCount());
- StatsReporter.SetActiveObjects(m_sceneGraph.GetActiveObjectsCount());
- StatsReporter.addFrameMS(frameMS);
- StatsReporter.addPhysicsMS(physicsMS + physicsMS2);
- StatsReporter.addOtherMS(otherMS);
- StatsReporter.SetActiveScripts(m_sceneGraph.GetActiveScriptsCount());
- StatsReporter.addScriptLines(m_sceneGraph.GetScriptLPS());
+ int terMS = Util.EnvironmentTickCount();
+ UpdateTerrain();
+ terrainMS = Util.EnvironmentTickCountSubtract(terMS);
}
- if (LoginsDisabled && m_frame == 20)
- {
- // In 99.9% of cases it is a bad idea to manually force garbage collection. However,
- // this is a rare case where we know we have just went through a long cycle of heap
- // allocations, and there is no more work to be done until someone logs in
- GC.Collect();
+ //if (Frame % m_update_land == 0)
+ //{
+ // int ldMS = Util.EnvironmentTickCount();
+ // UpdateLand();
+ // landMS = Util.EnvironmentTickCountSubtract(ldMS);
+ //}
- IConfig startupConfig = m_config.Configs["Startup"];
- if (startupConfig == null || !startupConfig.GetBoolean("StartDisabled", false))
- {
- m_log.DebugFormat("[REGION]: Enabling logins for {0}", RegionInfo.RegionName);
- LoginsDisabled = false;
- m_sceneGridService.InformNeighborsThatRegionisUp(RequestModuleInterface(), RegionInfo);
- }
+ frameMS = Util.EnvironmentTickCountSubtract(tmpFrameMS);
+ otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS;
+ lastCompletedFrame = Util.EnvironmentTickCount();
+
+ // if (Frame%m_update_avatars == 0)
+ // UpdateInWorldTime();
+ StatsReporter.AddPhysicsFPS(physicsFPS);
+ StatsReporter.AddTimeDilation(TimeDilation);
+ StatsReporter.AddFPS(1);
+ StatsReporter.SetRootAgents(m_sceneGraph.GetRootAgentCount());
+ StatsReporter.SetChildAgents(m_sceneGraph.GetChildAgentCount());
+ StatsReporter.SetObjects(m_sceneGraph.GetTotalObjectsCount());
+ StatsReporter.SetActiveObjects(m_sceneGraph.GetActiveObjectsCount());
+ StatsReporter.addFrameMS(frameMS);
+ StatsReporter.addPhysicsMS(physicsMS + physicsMS2);
+ StatsReporter.addOtherMS(otherMS);
+ StatsReporter.SetActiveScripts(m_sceneGraph.GetActiveScriptsCount());
+ StatsReporter.addScriptLines(m_sceneGraph.GetScriptLPS());
+ }
+
+ if (LoginsDisabled && Frame == 20)
+ {
+ // In 99.9% of cases it is a bad idea to manually force garbage collection. However,
+ // this is a rare case where we know we have just went through a long cycle of heap
+ // allocations, and there is no more work to be done until someone logs in
+ GC.Collect();
+
+ IConfig startupConfig = m_config.Configs["Startup"];
+ if (startupConfig == null || !startupConfig.GetBoolean("StartDisabled", false))
+ {
+ m_log.DebugFormat("[REGION]: Enabling logins for {0}", RegionInfo.RegionName);
+ LoginsDisabled = false;
+ m_sceneGridService.InformNeighborsThatRegionisUp(RequestModuleInterface(), RegionInfo);
}
}
- catch (NotImplementedException)
- {
- throw;
- }
- catch (AccessViolationException e)
- {
- m_log.Error("[REGION]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName);
- }
- //catch (NullReferenceException e)
- //{
- // m_log.Error("[REGION]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName);
- //}
- catch (InvalidOperationException e)
- {
- m_log.Error("[REGION]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName);
- }
- catch (Exception e)
- {
- m_log.Error("[REGION]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName);
- }
- finally
- {
- m_lastupdate = DateTime.UtcNow;
- }
-
- maintc = Util.EnvironmentTickCountSubtract(maintc);
- maintc = (int)(m_timespan * 1000) - maintc;
-
- if (maintc > 0)
- Thread.Sleep(maintc);
-
- // Tell the watchdog that this thread is still alive
- Watchdog.UpdateThread();
}
- }
+ catch (NotImplementedException)
+ {
+ throw;
+ }
+ catch (AccessViolationException e)
+ {
+ m_log.Error("[REGION]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName);
+ }
+ //catch (NullReferenceException e)
+ //{
+ // m_log.Error("[REGION]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName);
+ //}
+ catch (InvalidOperationException e)
+ {
+ m_log.Error("[REGION]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName);
+ }
+ catch (Exception e)
+ {
+ m_log.Error("[REGION]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName);
+ }
+ finally
+ {
+ m_lastupdate = DateTime.UtcNow;
+ }
-
+ maintc = Util.EnvironmentTickCountSubtract(maintc);
+ maintc = (int)(m_timespan * 1000) - maintc;
+
+ if (maintc > 0)
+ Thread.Sleep(maintc);
+
+ // Tell the watchdog that this thread is still alive
+ Watchdog.UpdateThread();
+ }
public void AddGroupTarget(SceneObjectGroup grp)
{
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs
index ef52363611..8286e4f919 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs
@@ -116,9 +116,6 @@ namespace OpenSim.Region.Framework.Scenes.Tests
agent.ChildrenCapSeeds = new Dictionary();
agent.child = true;
- if (scene.PresenceService == null)
- Console.WriteLine("Presence Service is null");
-
scene.PresenceService.LoginAgent(agent.AgentID.ToString(), agent.SessionID, agent.SecureSessionID);
string reason;
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs
new file mode 100644
index 0000000000..9aba8a8bfc
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSimulator Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Text;
+using System.Threading;
+using System.Timers;
+using Timer=System.Timers.Timer;
+using Nini.Config;
+using NUnit.Framework;
+using NUnit.Framework.SyntaxHelpers;
+using OpenMetaverse;
+using OpenSim.Framework;
+using OpenSim.Framework.Communications;
+using OpenSim.Region.Framework.Scenes;
+using OpenSim.Region.Framework.Interfaces;
+using OpenSim.Region.CoreModules.World.Serialiser;
+using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation;
+using OpenSim.Tests.Common;
+using OpenSim.Tests.Common.Mock;
+using OpenSim.Tests.Common.Setup;
+
+namespace OpenSim.Region.Framework.Scenes.Tests
+{
+ ///
+ /// Scene presence tests
+ ///
+ [TestFixture]
+ public class SceneTests
+ {
+ ///
+ /// Very basic scene update test. Should become more elaborate with time.
+ ///
+ [Test]
+ public void TestUpdateScene()
+ {
+ TestHelper.InMethod();
+
+ Scene scene = SceneSetupHelpers.SetupScene();
+ scene.Update();
+
+ Assert.That(scene.Frame, Is.EqualTo(1));
+ }
+ }
+}
\ No newline at end of file