aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes/Scene.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/Scene.cs')
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs352
1 files changed, 186 insertions, 166 deletions
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 0706905..790ec63 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -190,7 +190,11 @@ namespace OpenSim.Region.Framework.Scenes
190 private int backupMS; 190 private int backupMS;
191 private int terrainMS; 191 private int terrainMS;
192 private int landMS; 192 private int landMS;
193 private int lastCompletedFrame; 193
194 /// <summary>
195 /// Tick at which the last frame was processed.
196 /// </summary>
197 private int m_lastFrameTick;
194 198
195 /// <summary> 199 /// <summary>
196 /// Signals whether temporary objects are currently being cleaned up. Needed because this is launched 200 /// Signals whether temporary objects are currently being cleaned up. Needed because this is launched
@@ -464,7 +468,7 @@ namespace OpenSim.Region.Framework.Scenes
464 public int MonitorBackupTime { get { return backupMS; } } 468 public int MonitorBackupTime { get { return backupMS; } }
465 public int MonitorTerrainTime { get { return terrainMS; } } 469 public int MonitorTerrainTime { get { return terrainMS; } }
466 public int MonitorLandTime { get { return landMS; } } 470 public int MonitorLandTime { get { return landMS; } }
467 public int MonitorLastFrameTick { get { return lastCompletedFrame; } } 471 public int MonitorLastFrameTick { get { return m_lastFrameTick; } }
468 472
469 public UpdatePrioritizationSchemes UpdatePrioritizationScheme { get { return m_priorityScheme; } } 473 public UpdatePrioritizationSchemes UpdatePrioritizationScheme { get { return m_priorityScheme; } }
470 public bool IsReprioritizationEnabled { get { return m_reprioritizationEnabled; } } 474 public bool IsReprioritizationEnabled { get { return m_reprioritizationEnabled; } }
@@ -1175,18 +1179,15 @@ namespace OpenSim.Region.Framework.Scenes
1175 // The first frame can take a very long time due to physics actors being added on startup. Therefore, 1179 // The first frame can take a very long time due to physics actors being added on startup. Therefore,
1176 // don't turn on the watchdog alarm for this thread until the second frame, in order to prevent false 1180 // don't turn on the watchdog alarm for this thread until the second frame, in order to prevent false
1177 // alarms for scenes with many objects. 1181 // alarms for scenes with many objects.
1178 Update(); 1182 Update(1);
1179 Watchdog.GetCurrentThreadInfo().AlarmIfTimeout = true; 1183 Watchdog.GetCurrentThreadInfo().AlarmIfTimeout = true;
1180 1184
1181 while (!shuttingdown) 1185 while (!shuttingdown)
1182 Update(); 1186 Update(-1);
1183 1187
1184 m_lastUpdate = Util.EnvironmentTickCount(); 1188 m_lastUpdate = Util.EnvironmentTickCount();
1185 m_firstHeartbeat = false; 1189 m_firstHeartbeat = false;
1186 } 1190 }
1187 catch (ThreadAbortException)
1188 {
1189 }
1190 finally 1191 finally
1191 { 1192 {
1192 Monitor.Pulse(m_heartbeatLock); 1193 Monitor.Pulse(m_heartbeatLock);
@@ -1196,188 +1197,207 @@ namespace OpenSim.Region.Framework.Scenes
1196 Watchdog.RemoveThread(); 1197 Watchdog.RemoveThread();
1197 } 1198 }
1198 1199
1199 public override void Update() 1200 public override void Update(int frames)
1200 { 1201 {
1201 float physicsFPS = 0f; 1202 long? endFrame = null;
1202 1203
1203 int maintc = Util.EnvironmentTickCount(); 1204 if (frames >= 0)
1204 int tmpFrameMS = maintc; 1205 endFrame = Frame + frames;
1205 agentMS = tempOnRezMS = eventMS = backupMS = terrainMS = landMS = 0;
1206 1206
1207 ++Frame; 1207 float physicsFPS = 0f;
1208 1208 int tmpPhysicsMS, tmpPhysicsMS2, tmpAgentMS, tmpTempOnRezMS, evMS, backMS, terMS;
1209// m_log.DebugFormat("[SCENE]: Processing frame {0} in {1}", Frame, RegionInfo.RegionName); 1209 int previousFrameTick;
1210 int maintc;
1211 List<Vector3> coarseLocations;
1212 List<UUID> avatarUUIDs;
1210 1213
1211 try 1214 while (!shuttingdown && (endFrame == null || Frame < endFrame))
1212 { 1215 {
1213 int tmpPhysicsMS2 = Util.EnvironmentTickCount(); 1216 maintc = Util.EnvironmentTickCount();
1214 if ((Frame % m_update_physics == 0) && m_physics_enabled) 1217 ++Frame;
1215 m_sceneGraph.UpdatePreparePhysics();
1216 physicsMS2 = Util.EnvironmentTickCountSubtract(tmpPhysicsMS2);
1217
1218 // Apply any pending avatar force input to the avatar's velocity
1219 int tmpAgentMS = Util.EnvironmentTickCount();
1220 if (Frame % m_update_entitymovement == 0)
1221 m_sceneGraph.UpdateScenePresenceMovement();
1222 agentMS = Util.EnvironmentTickCountSubtract(tmpAgentMS);
1223
1224 // Perform the main physics update. This will do the actual work of moving objects and avatars according to their
1225 // velocity
1226 int tmpPhysicsMS = Util.EnvironmentTickCount();
1227 if (Frame % m_update_physics == 0)
1228 {
1229 if (m_physics_enabled)
1230 physicsFPS = m_sceneGraph.UpdatePhysics(MinFrameTime);
1231 1218
1232 if (SynchronizeScene != null) 1219// m_log.DebugFormat("[SCENE]: Processing frame {0} in {1}", Frame, RegionInfo.RegionName);
1233 SynchronizeScene(this);
1234 }
1235 physicsMS = Util.EnvironmentTickCountSubtract(tmpPhysicsMS);
1236
1237 tmpAgentMS = Util.EnvironmentTickCount();
1238
1239 // Check if any objects have reached their targets
1240 CheckAtTargets();
1241
1242 // Update SceneObjectGroups that have scheduled themselves for updates
1243 // Objects queue their updates onto all scene presences
1244 if (Frame % m_update_objects == 0)
1245 m_sceneGraph.UpdateObjectGroups();
1246 1220
1247 // Run through all ScenePresences looking for updates 1221 agentMS = tempOnRezMS = eventMS = backupMS = terrainMS = landMS = 0;
1248 // Presence updates and queued object updates for each presence are sent to clients
1249 if (Frame % m_update_presences == 0)
1250 m_sceneGraph.UpdatePresences();
1251 1222
1252 // Coarse locations relate to positions of green dots on the mini-map (on a SecondLife client) 1223 try
1253 if (Frame % m_update_coarse_locations == 0)
1254 { 1224 {
1255 List<Vector3> coarseLocations; 1225 tmpPhysicsMS2 = Util.EnvironmentTickCount();
1256 List<UUID> avatarUUIDs; 1226 if ((Frame % m_update_physics == 0) && m_physics_enabled)
1257 SceneGraph.GetCoarseLocations(out coarseLocations, out avatarUUIDs, 60); 1227 m_sceneGraph.UpdatePreparePhysics();
1258 // Send coarse locations to clients 1228 physicsMS2 = Util.EnvironmentTickCountSubtract(tmpPhysicsMS2);
1259 ForEachScenePresence(delegate(ScenePresence presence) 1229
1230 // Apply any pending avatar force input to the avatar's velocity
1231 tmpAgentMS = Util.EnvironmentTickCount();
1232 if (Frame % m_update_entitymovement == 0)
1233 m_sceneGraph.UpdateScenePresenceMovement();
1234 agentMS = Util.EnvironmentTickCountSubtract(tmpAgentMS);
1235
1236 // Perform the main physics update. This will do the actual work of moving objects and avatars according to their
1237 // velocity
1238 tmpPhysicsMS = Util.EnvironmentTickCount();
1239 if (Frame % m_update_physics == 0)
1260 { 1240 {
1261 presence.SendCoarseLocations(coarseLocations, avatarUUIDs); 1241 if (m_physics_enabled)
1262 }); 1242 physicsFPS = m_sceneGraph.UpdatePhysics(MinFrameTime);
1263 } 1243
1264 1244 if (SynchronizeScene != null)
1265 agentMS += Util.EnvironmentTickCountSubtract(tmpAgentMS); 1245 SynchronizeScene(this);
1266 1246 }
1267 // Delete temp-on-rez stuff 1247 physicsMS = Util.EnvironmentTickCountSubtract(tmpPhysicsMS);
1268 if (Frame % m_update_temp_cleaning == 0 && !m_cleaningTemps)
1269 {
1270 int tmpTempOnRezMS = Util.EnvironmentTickCount();
1271 m_cleaningTemps = true;
1272 Util.FireAndForget(delegate { CleanTempObjects(); m_cleaningTemps = false; });
1273 tempOnRezMS = Util.EnvironmentTickCountSubtract(tmpTempOnRezMS);
1274 }
1275
1276 if (Frame % m_update_events == 0)
1277 {
1278 int evMS = Util.EnvironmentTickCount();
1279 UpdateEvents();
1280 eventMS = Util.EnvironmentTickCountSubtract(evMS); ;
1281 }
1282
1283 if (Frame % m_update_backup == 0)
1284 {
1285 int backMS = Util.EnvironmentTickCount();
1286 UpdateStorageBackup();
1287 backupMS = Util.EnvironmentTickCountSubtract(backMS);
1288 }
1289
1290 if (Frame % m_update_terrain == 0)
1291 {
1292 int terMS = Util.EnvironmentTickCount();
1293 UpdateTerrain();
1294 terrainMS = Util.EnvironmentTickCountSubtract(terMS);
1295 }
1296
1297 //if (Frame % m_update_land == 0)
1298 //{
1299 // int ldMS = Util.EnvironmentTickCount();
1300 // UpdateLand();
1301 // landMS = Util.EnvironmentTickCountSubtract(ldMS);
1302 //}
1303
1304 frameMS = Util.EnvironmentTickCountSubtract(tmpFrameMS);
1305 otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS;
1306 lastCompletedFrame = Util.EnvironmentTickCount();
1307
1308 // if (Frame%m_update_avatars == 0)
1309 // UpdateInWorldTime();
1310 StatsReporter.AddPhysicsFPS(physicsFPS);
1311 StatsReporter.AddTimeDilation(TimeDilation);
1312 StatsReporter.AddFPS(1);
1313 StatsReporter.SetRootAgents(m_sceneGraph.GetRootAgentCount());
1314 StatsReporter.SetChildAgents(m_sceneGraph.GetChildAgentCount());
1315 StatsReporter.SetObjects(m_sceneGraph.GetTotalObjectsCount());
1316 StatsReporter.SetActiveObjects(m_sceneGraph.GetActiveObjectsCount());
1317 StatsReporter.addFrameMS(frameMS);
1318 StatsReporter.addAgentMS(agentMS);
1319 StatsReporter.addPhysicsMS(physicsMS + physicsMS2);
1320 StatsReporter.addOtherMS(otherMS);
1321 StatsReporter.SetActiveScripts(m_sceneGraph.GetActiveScriptsCount());
1322 StatsReporter.addScriptLines(m_sceneGraph.GetScriptLPS());
1323
1324 if (LoginsDisabled && Frame == 20)
1325 {
1326// m_log.DebugFormat("{0} {1} {2}", LoginsDisabled, m_sceneGraph.GetActiveScriptsCount(), LoginLock);
1327 1248
1328 // In 99.9% of cases it is a bad idea to manually force garbage collection. However, 1249 tmpAgentMS = Util.EnvironmentTickCount();
1329 // this is a rare case where we know we have just went through a long cycle of heap 1250
1330 // allocations, and there is no more work to be done until someone logs in 1251 // Check if any objects have reached their targets
1331 GC.Collect(); 1252 CheckAtTargets();
1253
1254 // Update SceneObjectGroups that have scheduled themselves for updates
1255 // Objects queue their updates onto all scene presences
1256 if (Frame % m_update_objects == 0)
1257 m_sceneGraph.UpdateObjectGroups();
1258
1259 // Run through all ScenePresences looking for updates
1260 // Presence updates and queued object updates for each presence are sent to clients
1261 if (Frame % m_update_presences == 0)
1262 m_sceneGraph.UpdatePresences();
1263
1264 // Coarse locations relate to positions of green dots on the mini-map (on a SecondLife client)
1265 if (Frame % m_update_coarse_locations == 0)
1266 {
1267 SceneGraph.GetCoarseLocations(out coarseLocations, out avatarUUIDs, 60);
1268 // Send coarse locations to clients
1269 ForEachScenePresence(delegate(ScenePresence presence)
1270 {
1271 presence.SendCoarseLocations(coarseLocations, avatarUUIDs);
1272 });
1273 }
1274
1275 agentMS += Util.EnvironmentTickCountSubtract(tmpAgentMS);
1276
1277 // Delete temp-on-rez stuff
1278 if (Frame % m_update_temp_cleaning == 0 && !m_cleaningTemps)
1279 {
1280 tmpTempOnRezMS = Util.EnvironmentTickCount();
1281 m_cleaningTemps = true;
1282 Util.FireAndForget(delegate { CleanTempObjects(); m_cleaningTemps = false; });
1283 tempOnRezMS = Util.EnvironmentTickCountSubtract(tmpTempOnRezMS);
1284 }
1285
1286 if (Frame % m_update_events == 0)
1287 {
1288 evMS = Util.EnvironmentTickCount();
1289 UpdateEvents();
1290 eventMS = Util.EnvironmentTickCountSubtract(evMS);
1291 }
1292
1293 if (Frame % m_update_backup == 0)
1294 {
1295 backMS = Util.EnvironmentTickCount();
1296 UpdateStorageBackup();
1297 backupMS = Util.EnvironmentTickCountSubtract(backMS);
1298 }
1299
1300 if (Frame % m_update_terrain == 0)
1301 {
1302 terMS = Util.EnvironmentTickCount();
1303 UpdateTerrain();
1304 terrainMS = Util.EnvironmentTickCountSubtract(terMS);
1305 }
1306
1307 //if (Frame % m_update_land == 0)
1308 //{
1309 // int ldMS = Util.EnvironmentTickCount();
1310 // UpdateLand();
1311 // landMS = Util.EnvironmentTickCountSubtract(ldMS);
1312 //}
1332 1313
1333 IConfig startupConfig = m_config.Configs["Startup"]; 1314 frameMS = Util.EnvironmentTickCountSubtract(maintc);
1334 if (startupConfig == null || !startupConfig.GetBoolean("StartDisabled", false)) 1315 otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS;
1316
1317 // if (Frame%m_update_avatars == 0)
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
1327 // frameMS currently records work frame times, not total frame times (work + any required sleep to
1328 // reach min frame time.
1329 StatsReporter.addFrameMS(frameMS);
1330
1331 StatsReporter.addAgentMS(agentMS);
1332 StatsReporter.addPhysicsMS(physicsMS + physicsMS2);
1333 StatsReporter.addOtherMS(otherMS);
1334 StatsReporter.SetActiveScripts(m_sceneGraph.GetActiveScriptsCount());
1335 StatsReporter.addScriptLines(m_sceneGraph.GetScriptLPS());
1336
1337 if (LoginsDisabled && Frame == 20)
1335 { 1338 {
1336 // This handles a case of a region having no scripts for the RegionReady module 1339 // m_log.DebugFormat("{0} {1} {2}", LoginsDisabled, m_sceneGraph.GetActiveScriptsCount(), LoginLock);
1337 if (m_sceneGraph.GetActiveScriptsCount() == 0) 1340
1341 // In 99.9% of cases it is a bad idea to manually force garbage collection. However,
1342 // this is a rare case where we know we have just went through a long cycle of heap
1343 // allocations, and there is no more work to be done until someone logs in
1344 GC.Collect();
1345
1346 IConfig startupConfig = m_config.Configs["Startup"];
1347 if (startupConfig == null || !startupConfig.GetBoolean("StartDisabled", false))
1338 { 1348 {
1339 // need to be able to tell these have changed in RegionReady 1349 // This handles a case of a region having no scripts for the RegionReady module
1340 LoginLock = false; 1350 if (m_sceneGraph.GetActiveScriptsCount() == 0)
1341 EventManager.TriggerLoginsEnabled(RegionInfo.RegionName); 1351 {
1352 // need to be able to tell these have changed in RegionReady
1353 LoginLock = false;
1354 EventManager.TriggerLoginsEnabled(RegionInfo.RegionName);
1355 }
1356 m_log.DebugFormat("[REGION]: Enabling logins for {0}", RegionInfo.RegionName);
1357
1358 // For RegionReady lockouts
1359 if(LoginLock == false)
1360 {
1361 LoginsDisabled = false;
1362 }
1363
1364 m_sceneGridService.InformNeighborsThatRegionisUp(RequestModuleInterface<INeighbourService>(), RegionInfo);
1342 } 1365 }
1343 m_log.DebugFormat("[REGION]: Enabling logins for {0}", RegionInfo.RegionName); 1366 else
1344
1345 // For RegionReady lockouts
1346 if(LoginLock == false)
1347 { 1367 {
1348 LoginsDisabled = false; 1368 StartDisabled = true;
1369 LoginsDisabled = true;
1349 } 1370 }
1350
1351 m_sceneGridService.InformNeighborsThatRegionisUp(RequestModuleInterface<INeighbourService>(), RegionInfo);
1352 }
1353 else
1354 {
1355 StartDisabled = true;
1356 LoginsDisabled = true;
1357 } 1371 }
1358 } 1372 }
1359 } 1373 catch (Exception e)
1360 catch (NotImplementedException) 1374 {
1361 { 1375 m_log.ErrorFormat(
1362 throw; 1376 "[SCENE]: Failed on region {0} with exception {1}{2}",
1363 } 1377 RegionInfo.RegionName, e.Message, e.StackTrace);
1364 catch (Exception e) 1378 }
1365 { 1379
1366 m_log.ErrorFormat( 1380 EventManager.TriggerRegionHeartbeatEnd(this);
1367 "[SCENE]: Failed on region {0} with exception {1}{2}",
1368 RegionInfo.RegionName, e.Message, e.StackTrace);
1369 }
1370 1381
1371 EventManager.TriggerRegionHeartbeatEnd(this); 1382 // Tell the watchdog that this thread is still alive
1383 Watchdog.UpdateThread();
1372 1384
1373 maintc = Util.EnvironmentTickCountSubtract(maintc); 1385// previousFrameTick = m_lastFrameTick;
1374 maintc = (int)(MinFrameTime * 1000) - maintc; 1386 m_lastFrameTick = Util.EnvironmentTickCount();
1387 maintc = Util.EnvironmentTickCountSubtract(m_lastFrameTick, maintc);
1388 maintc = (int)(MinFrameTime * 1000) - maintc;
1375 1389
1376 if (maintc > 0) 1390 if (maintc > 0)
1377 Thread.Sleep(maintc); 1391 Thread.Sleep(maintc);
1378 1392
1379 // Tell the watchdog that this thread is still alive 1393 // Optionally warn if a frame takes double the amount of time that it should.
1380 Watchdog.UpdateThread(); 1394// if (Util.EnvironmentTickCountSubtract(m_lastFrameTick, previousFrameTick) > (int)(MinFrameTime * 1000 * 2))
1395// m_log.WarnFormat(
1396// "[SCENE]: Frame took {0} ms (desired max {1} ms) in {2}",
1397// Util.EnvironmentTickCountSubtract(m_lastFrameTick, previousFrameTick),
1398// MinFrameTime * 1000,
1399// RegionInfo.RegionName);
1400 }
1381 } 1401 }
1382 1402
1383 public void AddGroupTarget(SceneObjectGroup grp) 1403 public void AddGroupTarget(SceneObjectGroup grp)