aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework')
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs307
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs3
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs71
3 files changed, 224 insertions, 157 deletions
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 02a0268..e0af2d6 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -129,7 +129,16 @@ namespace OpenSim.Region.Framework.Scenes
129 protected ICapabilitiesModule m_capsModule; 129 protected ICapabilitiesModule m_capsModule;
130 // Central Update Loop 130 // Central Update Loop
131 protected int m_fps = 10; 131 protected int m_fps = 10;
132 protected uint m_frame; 132
133 /// <summary>
134 /// Current scene frame number
135 /// </summary>
136 public uint Frame
137 {
138 get;
139 protected set;
140 }
141
133 protected float m_timespan = 0.089f; 142 protected float m_timespan = 0.089f;
134 protected DateTime m_lastupdate = DateTime.UtcNow; 143 protected DateTime m_lastupdate = DateTime.UtcNow;
135 144
@@ -1183,7 +1192,8 @@ namespace OpenSim.Region.Framework.Scenes
1183 1192
1184 try 1193 try
1185 { 1194 {
1186 Update(); 1195 while (!shuttingdown)
1196 Update();
1187 1197
1188 m_lastUpdate = Util.EnvironmentTickCount(); 1198 m_lastUpdate = Util.EnvironmentTickCount();
1189 m_firstHeartbeat = false; 1199 m_firstHeartbeat = false;
@@ -1200,187 +1210,176 @@ namespace OpenSim.Region.Framework.Scenes
1200 Watchdog.RemoveThread(); 1210 Watchdog.RemoveThread();
1201 } 1211 }
1202 1212
1203 /// <summary>
1204 /// Performs per-frame updates on the scene, this should be the central scene loop
1205 /// </summary>
1206 public override void Update() 1213 public override void Update()
1207 { 1214 {
1208 float physicsFPS; 1215 TimeSpan SinceLastFrame = DateTime.UtcNow - m_lastupdate;
1209 int maintc; 1216 float physicsFPS = 0f;
1210 1217
1211 while (!shuttingdown) 1218 int maintc = Util.EnvironmentTickCount();
1219 int tmpFrameMS = maintc;
1220 tempOnRezMS = eventMS = backupMS = terrainMS = landMS = 0;
1221
1222 // Increment the frame counter
1223 ++Frame;
1224
1225 try
1212 { 1226 {
1213 TimeSpan SinceLastFrame = DateTime.UtcNow - m_lastupdate; 1227 // Check if any objects have reached their targets
1214 physicsFPS = 0f; 1228 CheckAtTargets();
1215 1229
1216 maintc = Util.EnvironmentTickCount(); 1230 // Update SceneObjectGroups that have scheduled themselves for updates
1217 int tmpFrameMS = maintc; 1231 // Objects queue their updates onto all scene presences
1218 tempOnRezMS = eventMS = backupMS = terrainMS = landMS = 0; 1232 if (Frame % m_update_objects == 0)
1233 m_sceneGraph.UpdateObjectGroups();
1219 1234
1220 // Increment the frame counter 1235 // Run through all ScenePresences looking for updates
1221 ++m_frame; 1236 // Presence updates and queued object updates for each presence are sent to clients
1237 if (Frame % m_update_presences == 0)
1238 m_sceneGraph.UpdatePresences();
1222 1239
1223 try 1240 // Coarse locations relate to positions of green dots on the mini-map (on a SecondLife client)
1241 if (Frame % m_update_coarse_locations == 0)
1224 { 1242 {
1225 // Check if any objects have reached their targets 1243 List<Vector3> coarseLocations;
1226 CheckAtTargets(); 1244 List<UUID> avatarUUIDs;
1227 1245 SceneGraph.GetCoarseLocations(out coarseLocations, out avatarUUIDs, 60);
1228 // Update SceneObjectGroups that have scheduled themselves for updates 1246 // Send coarse locations to clients
1229 // Objects queue their updates onto all scene presences 1247 ForEachScenePresence(delegate(ScenePresence presence)
1230 if (m_frame % m_update_objects == 0) 1248 {
1231 m_sceneGraph.UpdateObjectGroups(); 1249 presence.SendCoarseLocations(coarseLocations, avatarUUIDs);
1250 });
1251 }
1232 1252
1233 // Run through all ScenePresences looking for updates 1253 int tmpPhysicsMS2 = Util.EnvironmentTickCount();
1234 // Presence updates and queued object updates for each presence are sent to clients 1254 if ((Frame % m_update_physics == 0) && m_physics_enabled)
1235 if (m_frame % m_update_presences == 0) 1255 m_sceneGraph.UpdatePreparePhysics();
1236 m_sceneGraph.UpdatePresences(); 1256 physicsMS2 = Util.EnvironmentTickCountSubtract(tmpPhysicsMS2);
1237 1257
1238 // Coarse locations relate to positions of green dots on the mini-map (on a SecondLife client) 1258 // Apply any pending avatar force input to the avatar's velocity
1239 if (m_frame % m_update_coarse_locations == 0) 1259 if (Frame % m_update_entitymovement == 0)
1240 { 1260 m_sceneGraph.UpdateScenePresenceMovement();
1241 List<Vector3> coarseLocations;
1242 List<UUID> avatarUUIDs;
1243 SceneGraph.GetCoarseLocations(out coarseLocations, out avatarUUIDs, 60);
1244 // Send coarse locations to clients
1245 ForEachScenePresence(delegate(ScenePresence presence)
1246 {
1247 presence.SendCoarseLocations(coarseLocations, avatarUUIDs);
1248 });
1249 }
1250 1261
1251 int tmpPhysicsMS2 = Util.EnvironmentTickCount(); 1262 // Perform the main physics update. This will do the actual work of moving objects and avatars according to their
1252 if ((m_frame % m_update_physics == 0) && m_physics_enabled) 1263 // velocity
1253 m_sceneGraph.UpdatePreparePhysics(); 1264 int tmpPhysicsMS = Util.EnvironmentTickCount();
1254 physicsMS2 = Util.EnvironmentTickCountSubtract(tmpPhysicsMS2); 1265 if (Frame % m_update_physics == 0)
1266 {
1267 if (m_physics_enabled)
1268 physicsFPS = m_sceneGraph.UpdatePhysics(Math.Max(SinceLastFrame.TotalSeconds, m_timespan));
1269 if (SynchronizeScene != null)
1270 SynchronizeScene(this);
1271 }
1272 physicsMS = Util.EnvironmentTickCountSubtract(tmpPhysicsMS);
1255 1273
1256 // Apply any pending avatar force input to the avatar's velocity 1274 // Delete temp-on-rez stuff
1257 if (m_frame % m_update_entitymovement == 0) 1275 if (Frame % 1000 == 0 && !m_cleaningTemps)
1258 m_sceneGraph.UpdateScenePresenceMovement(); 1276 {
1277 int tmpTempOnRezMS = Util.EnvironmentTickCount();
1278 m_cleaningTemps = true;
1279 Util.FireAndForget(delegate { CleanTempObjects(); m_cleaningTemps = false; });
1280 tempOnRezMS = Util.EnvironmentTickCountSubtract(tmpTempOnRezMS);
1281 }
1259 1282
1260 // Perform the main physics update. This will do the actual work of moving objects and avatars according to their 1283 if (RegionStatus != RegionStatus.SlaveScene)
1261 // velocity 1284 {
1262 int tmpPhysicsMS = Util.EnvironmentTickCount(); 1285 if (Frame % m_update_events == 0)
1263 if (m_frame % m_update_physics == 0)
1264 { 1286 {
1265 if (m_physics_enabled) 1287 int evMS = Util.EnvironmentTickCount();
1266 physicsFPS = m_sceneGraph.UpdatePhysics(Math.Max(SinceLastFrame.TotalSeconds, m_timespan)); 1288 UpdateEvents();
1267 if (SynchronizeScene != null) 1289 eventMS = Util.EnvironmentTickCountSubtract(evMS); ;
1268 SynchronizeScene(this);
1269 } 1290 }
1270 physicsMS = Util.EnvironmentTickCountSubtract(tmpPhysicsMS);
1271 1291
1272 // Delete temp-on-rez stuff 1292 if (Frame % m_update_backup == 0)
1273 if (m_frame % 1000 == 0 && !m_cleaningTemps)
1274 { 1293 {
1275 int tmpTempOnRezMS = Util.EnvironmentTickCount(); 1294 int backMS = Util.EnvironmentTickCount();
1276 m_cleaningTemps = true; 1295 UpdateStorageBackup();
1277 Util.FireAndForget(delegate { CleanTempObjects(); m_cleaningTemps = false; }); 1296 backupMS = Util.EnvironmentTickCountSubtract(backMS);
1278 tempOnRezMS = Util.EnvironmentTickCountSubtract(tmpTempOnRezMS);
1279 } 1297 }
1280 1298
1281 if (RegionStatus != RegionStatus.SlaveScene) 1299 if (Frame % m_update_terrain == 0)
1282 { 1300 {
1283 if (m_frame % m_update_events == 0) 1301 int terMS = Util.EnvironmentTickCount();
1284 { 1302 UpdateTerrain();
1285 int evMS = Util.EnvironmentTickCount(); 1303 terrainMS = Util.EnvironmentTickCountSubtract(terMS);
1286 UpdateEvents(); 1304 }
1287 eventMS = Util.EnvironmentTickCountSubtract(evMS); ;
1288 }
1289
1290 if (m_frame % m_update_backup == 0)
1291 {
1292 int backMS = Util.EnvironmentTickCount();
1293 UpdateStorageBackup();
1294 backupMS = Util.EnvironmentTickCountSubtract(backMS);
1295 }
1296 1305
1297 if (m_frame % m_update_terrain == 0) 1306 //if (Frame % m_update_land == 0)
1298 { 1307 //{
1299 int terMS = Util.EnvironmentTickCount(); 1308 // int ldMS = Util.EnvironmentTickCount();
1300 UpdateTerrain(); 1309 // UpdateLand();
1301 terrainMS = Util.EnvironmentTickCountSubtract(terMS); 1310 // landMS = Util.EnvironmentTickCountSubtract(ldMS);
1302 } 1311 //}
1303 1312
1304 //if (m_frame % m_update_land == 0) 1313 frameMS = Util.EnvironmentTickCountSubtract(tmpFrameMS);
1305 //{ 1314 otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS;
1306 // int ldMS = Util.EnvironmentTickCount(); 1315 lastCompletedFrame = Util.EnvironmentTickCount();
1307 // UpdateLand(); 1316
1308 // landMS = Util.EnvironmentTickCountSubtract(ldMS); 1317 // if (Frame%m_update_avatars == 0)
1309 //} 1318 // UpdateInWorldTime();
1319 StatsReporter.AddPhysicsFPS(physicsFPS);
1320 StatsReporter.AddTimeDilation(TimeDilation);
1321 StatsReporter.AddFPS(1);
1322 StatsReporter.SetRootAgents(m_sceneGraph.GetRootAgentCount());
1323 StatsReporter.SetChildAgents(m_sceneGraph.GetChildAgentCount());
1324 StatsReporter.SetObjects(m_sceneGraph.GetTotalObjectsCount());
1325 StatsReporter.SetActiveObjects(m_sceneGraph.GetActiveObjectsCount());
1326 StatsReporter.addFrameMS(frameMS);
1327 StatsReporter.addPhysicsMS(physicsMS + physicsMS2);
1328 StatsReporter.addOtherMS(otherMS);
1329 StatsReporter.SetActiveScripts(m_sceneGraph.GetActiveScriptsCount());
1330 StatsReporter.addScriptLines(m_sceneGraph.GetScriptLPS());
1331 }
1310 1332
1311 frameMS = Util.EnvironmentTickCountSubtract(tmpFrameMS); 1333 if (LoginsDisabled && Frame == 20)
1312 otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS; 1334 {
1313 lastCompletedFrame = Util.EnvironmentTickCount(); 1335 // In 99.9% of cases it is a bad idea to manually force garbage collection. However,
1314 1336 // this is a rare case where we know we have just went through a long cycle of heap
1315 // if (m_frame%m_update_avatars == 0) 1337 // allocations, and there is no more work to be done until someone logs in
1316 // UpdateInWorldTime(); 1338 GC.Collect();
1317 StatsReporter.AddPhysicsFPS(physicsFPS);
1318 StatsReporter.AddTimeDilation(TimeDilation);
1319 StatsReporter.AddFPS(1);
1320 StatsReporter.SetRootAgents(m_sceneGraph.GetRootAgentCount());
1321 StatsReporter.SetChildAgents(m_sceneGraph.GetChildAgentCount());
1322 StatsReporter.SetObjects(m_sceneGraph.GetTotalObjectsCount());
1323 StatsReporter.SetActiveObjects(m_sceneGraph.GetActiveObjectsCount());
1324 StatsReporter.addFrameMS(frameMS);
1325 StatsReporter.addPhysicsMS(physicsMS + physicsMS2);
1326 StatsReporter.addOtherMS(otherMS);
1327 StatsReporter.SetActiveScripts(m_sceneGraph.GetActiveScriptsCount());
1328 StatsReporter.addScriptLines(m_sceneGraph.GetScriptLPS());
1329 }
1330 1339
1331 if (LoginsDisabled && m_frame == 20) 1340 IConfig startupConfig = m_config.Configs["Startup"];
1341 if (startupConfig == null || !startupConfig.GetBoolean("StartDisabled", false))
1332 { 1342 {
1333 // In 99.9% of cases it is a bad idea to manually force garbage collection. However, 1343 m_log.DebugFormat("[REGION]: Enabling logins for {0}", RegionInfo.RegionName);
1334 // this is a rare case where we know we have just went through a long cycle of heap 1344 LoginsDisabled = false;
1335 // allocations, and there is no more work to be done until someone logs in 1345 m_sceneGridService.InformNeighborsThatRegionisUp(RequestModuleInterface<INeighbourService>(), RegionInfo);
1336 GC.Collect();
1337
1338 IConfig startupConfig = m_config.Configs["Startup"];
1339 if (startupConfig == null || !startupConfig.GetBoolean("StartDisabled", false))
1340 {
1341 m_log.DebugFormat("[REGION]: Enabling logins for {0}", RegionInfo.RegionName);
1342 LoginsDisabled = false;
1343 m_sceneGridService.InformNeighborsThatRegionisUp(RequestModuleInterface<INeighbourService>(), RegionInfo);
1344 }
1345 } 1346 }
1346 } 1347 }
1347 catch (NotImplementedException) 1348 }
1348 { 1349 catch (NotImplementedException)
1349 throw; 1350 {
1350 } 1351 throw;
1351 catch (AccessViolationException e) 1352 }
1352 { 1353 catch (AccessViolationException e)
1353 m_log.Error("[REGION]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName); 1354 {
1354 } 1355 m_log.Error("[REGION]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName);
1355 //catch (NullReferenceException e) 1356 }
1356 //{ 1357 //catch (NullReferenceException e)
1357 // m_log.Error("[REGION]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName); 1358 //{
1358 //} 1359 // m_log.Error("[REGION]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName);
1359 catch (InvalidOperationException e) 1360 //}
1360 { 1361 catch (InvalidOperationException e)
1361 m_log.Error("[REGION]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName); 1362 {
1362 } 1363 m_log.Error("[REGION]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName);
1363 catch (Exception e) 1364 }
1364 { 1365 catch (Exception e)
1365 m_log.Error("[REGION]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName); 1366 {
1366 } 1367 m_log.Error("[REGION]: Failed with exception " + e.ToString() + " On Region: " + RegionInfo.RegionName);
1367 finally 1368 }
1368 { 1369 finally
1369 m_lastupdate = DateTime.UtcNow; 1370 {
1370 } 1371 m_lastupdate = DateTime.UtcNow;
1371 1372 }
1372 maintc = Util.EnvironmentTickCountSubtract(maintc);
1373 maintc = (int)(m_timespan * 1000) - maintc;
1374 1373
1375 if (maintc > 0) 1374 maintc = Util.EnvironmentTickCountSubtract(maintc);
1376 Thread.Sleep(maintc); 1375 maintc = (int)(m_timespan * 1000) - maintc;
1377 1376
1378 // Tell the watchdog that this thread is still alive 1377 if (maintc > 0)
1379 Watchdog.UpdateThread(); 1378 Thread.Sleep(maintc);
1380 }
1381 }
1382 1379
1383 1380 // Tell the watchdog that this thread is still alive
1381 Watchdog.UpdateThread();
1382 }
1384 1383
1385 public void AddGroupTarget(SceneObjectGroup grp) 1384 public void AddGroupTarget(SceneObjectGroup grp)
1386 { 1385 {
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs
index ef52363..8286e4f 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
116 agent.ChildrenCapSeeds = new Dictionary<ulong, string>(); 116 agent.ChildrenCapSeeds = new Dictionary<ulong, string>();
117 agent.child = true; 117 agent.child = true;
118 118
119 if (scene.PresenceService == null)
120 Console.WriteLine("Presence Service is null");
121
122 scene.PresenceService.LoginAgent(agent.AgentID.ToString(), agent.SessionID, agent.SecureSessionID); 119 scene.PresenceService.LoginAgent(agent.AgentID.ToString(), agent.SessionID, agent.SecureSessionID);
123 120
124 string reason; 121 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 0000000..9aba8a8
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs
@@ -0,0 +1,71 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using System.Text;
32using System.Threading;
33using System.Timers;
34using Timer=System.Timers.Timer;
35using Nini.Config;
36using NUnit.Framework;
37using NUnit.Framework.SyntaxHelpers;
38using OpenMetaverse;
39using OpenSim.Framework;
40using OpenSim.Framework.Communications;
41using OpenSim.Region.Framework.Scenes;
42using OpenSim.Region.Framework.Interfaces;
43using OpenSim.Region.CoreModules.World.Serialiser;
44using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation;
45using OpenSim.Tests.Common;
46using OpenSim.Tests.Common.Mock;
47using OpenSim.Tests.Common.Setup;
48
49namespace OpenSim.Region.Framework.Scenes.Tests
50{
51 /// <summary>
52 /// Scene presence tests
53 /// </summary>
54 [TestFixture]
55 public class SceneTests
56 {
57 /// <summary>
58 /// Very basic scene update test. Should become more elaborate with time.
59 /// </summary>
60 [Test]
61 public void TestUpdateScene()
62 {
63 TestHelper.InMethod();
64
65 Scene scene = SceneSetupHelpers.SetupScene();
66 scene.Update();
67
68 Assert.That(scene.Frame, Is.EqualTo(1));
69 }
70 }
71} \ No newline at end of file