diff options
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/Scene.cs')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/Scene.cs | 353 |
1 files changed, 184 insertions, 169 deletions
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index b50ccc4..2a511e4 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs | |||
@@ -1223,11 +1223,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
1223 | // The first frame can take a very long time due to physics actors being added on startup. Therefore, | 1223 | // The first frame can take a very long time due to physics actors being added on startup. Therefore, |
1224 | // don't turn on the watchdog alarm for this thread until the second frame, in order to prevent false | 1224 | // don't turn on the watchdog alarm for this thread until the second frame, in order to prevent false |
1225 | // alarms for scenes with many objects. | 1225 | // alarms for scenes with many objects. |
1226 | Update(); | 1226 | Update(1); |
1227 | Watchdog.GetCurrentThreadInfo().AlarmIfTimeout = true; | 1227 | Watchdog.GetCurrentThreadInfo().AlarmIfTimeout = true; |
1228 | 1228 | ||
1229 | while (!shuttingdown) | 1229 | while (!shuttingdown) |
1230 | Update(); | 1230 | Update(-1); |
1231 | |||
1232 | m_lastUpdate = Util.EnvironmentTickCount(); | ||
1233 | m_firstHeartbeat = false; | ||
1231 | } | 1234 | } |
1232 | finally | 1235 | finally |
1233 | { | 1236 | { |
@@ -1238,196 +1241,208 @@ namespace OpenSim.Region.Framework.Scenes | |||
1238 | Watchdog.RemoveThread(); | 1241 | Watchdog.RemoveThread(); |
1239 | } | 1242 | } |
1240 | 1243 | ||
1241 | public override void Update() | 1244 | public override void Update(int frames) |
1242 | { | 1245 | { |
1243 | float physicsFPS = 0f; | 1246 | long? endFrame = null; |
1244 | |||
1245 | int maintc = Util.EnvironmentTickCount(); | ||
1246 | int tmpFrameMS = maintc; | ||
1247 | agentMS = tempOnRezMS = eventMS = backupMS = terrainMS = landMS = 0; | ||
1248 | 1247 | ||
1249 | ++Frame; | 1248 | if (frames >= 0) |
1249 | endFrame = Frame + frames; | ||
1250 | 1250 | ||
1251 | // m_log.DebugFormat("[SCENE]: Processing frame {0} in {1}", Frame, RegionInfo.RegionName); | 1251 | float physicsFPS = 0f; |
1252 | int tmpPhysicsMS, tmpPhysicsMS2, tmpAgentMS, tmpTempOnRezMS, evMS, backMS, terMS; | ||
1253 | int maintc; | ||
1254 | List<Vector3> coarseLocations; | ||
1255 | List<UUID> avatarUUIDs; | ||
1252 | 1256 | ||
1253 | try | 1257 | while (!shuttingdown && (endFrame == null || Frame < endFrame)) |
1254 | { | 1258 | { |
1255 | int tmpPhysicsMS2 = Util.EnvironmentTickCount(); | 1259 | maintc = Util.EnvironmentTickCount(); |
1256 | if ((Frame % m_update_physics == 0) && m_physics_enabled) | 1260 | ++Frame; |
1257 | m_sceneGraph.UpdatePreparePhysics(); | ||
1258 | physicsMS2 = Util.EnvironmentTickCountSubtract(tmpPhysicsMS2); | ||
1259 | |||
1260 | // Apply any pending avatar force input to the avatar's velocity | ||
1261 | int tmpAgentMS = Util.EnvironmentTickCount(); | ||
1262 | if (Frame % m_update_entitymovement == 0) | ||
1263 | m_sceneGraph.UpdateScenePresenceMovement(); | ||
1264 | agentMS = Util.EnvironmentTickCountSubtract(tmpAgentMS); | ||
1265 | |||
1266 | // Perform the main physics update. This will do the actual work of moving objects and avatars according to their | ||
1267 | // velocity | ||
1268 | int tmpPhysicsMS = Util.EnvironmentTickCount(); | ||
1269 | if (Frame % m_update_physics == 0) | ||
1270 | { | ||
1271 | if (m_physics_enabled) | ||
1272 | physicsFPS = m_sceneGraph.UpdatePhysics(MinFrameTime); | ||
1273 | |||
1274 | if (SynchronizeScene != null) | ||
1275 | SynchronizeScene(this); | ||
1276 | } | ||
1277 | physicsMS = Util.EnvironmentTickCountSubtract(tmpPhysicsMS); | ||
1278 | 1261 | ||
1279 | tmpAgentMS = Util.EnvironmentTickCount(); | 1262 | // m_log.DebugFormat("[SCENE]: Processing frame {0} in {1}", Frame, RegionInfo.RegionName); |
1280 | |||
1281 | // Check if any objects have reached their targets | ||
1282 | CheckAtTargets(); | ||
1283 | |||
1284 | // Update SceneObjectGroups that have scheduled themselves for updates | ||
1285 | // Objects queue their updates onto all scene presences | ||
1286 | if (Frame % m_update_objects == 0) | ||
1287 | m_sceneGraph.UpdateObjectGroups(); | ||
1288 | 1263 | ||
1289 | // Run through all ScenePresences looking for updates | 1264 | agentMS = tempOnRezMS = eventMS = backupMS = terrainMS = landMS = 0; |
1290 | // Presence updates and queued object updates for each presence are sent to clients | ||
1291 | if (Frame % m_update_presences == 0) | ||
1292 | m_sceneGraph.UpdatePresences(); | ||
1293 | 1265 | ||
1294 | // Coarse locations relate to positions of green dots on the mini-map (on a SecondLife client) | 1266 | try |
1295 | if (Frame % m_update_coarse_locations == 0) | ||
1296 | { | 1267 | { |
1297 | List<Vector3> coarseLocations; | 1268 | tmpPhysicsMS2 = Util.EnvironmentTickCount(); |
1298 | List<UUID> avatarUUIDs; | 1269 | if ((Frame % m_update_physics == 0) && m_physics_enabled) |
1299 | SceneGraph.GetCoarseLocations(out coarseLocations, out avatarUUIDs, 60); | 1270 | m_sceneGraph.UpdatePreparePhysics(); |
1300 | // Send coarse locations to clients | 1271 | physicsMS2 = Util.EnvironmentTickCountSubtract(tmpPhysicsMS2); |
1301 | ForEachScenePresence(delegate(ScenePresence presence) | 1272 | |
1273 | // Apply any pending avatar force input to the avatar's velocity | ||
1274 | tmpAgentMS = Util.EnvironmentTickCount(); | ||
1275 | if (Frame % m_update_entitymovement == 0) | ||
1276 | m_sceneGraph.UpdateScenePresenceMovement(); | ||
1277 | agentMS = Util.EnvironmentTickCountSubtract(tmpAgentMS); | ||
1278 | |||
1279 | // Perform the main physics update. This will do the actual work of moving objects and avatars according to their | ||
1280 | // velocity | ||
1281 | tmpPhysicsMS = Util.EnvironmentTickCount(); | ||
1282 | if (Frame % m_update_physics == 0) | ||
1302 | { | 1283 | { |
1303 | presence.SendCoarseLocations(coarseLocations, avatarUUIDs); | 1284 | if (m_physics_enabled) |
1304 | }); | 1285 | physicsFPS = m_sceneGraph.UpdatePhysics(MinFrameTime); |
1305 | } | 1286 | |
1306 | 1287 | if (SynchronizeScene != null) | |
1307 | agentMS += Util.EnvironmentTickCountSubtract(tmpAgentMS); | 1288 | SynchronizeScene(this); |
1308 | 1289 | } | |
1309 | // Delete temp-on-rez stuff | 1290 | physicsMS = Util.EnvironmentTickCountSubtract(tmpPhysicsMS); |
1310 | if (Frame % m_update_temp_cleaning == 0 && !m_cleaningTemps) | ||
1311 | { | ||
1312 | int tmpTempOnRezMS = Util.EnvironmentTickCount(); | ||
1313 | m_cleaningTemps = true; | ||
1314 | Util.FireAndForget(delegate { CleanTempObjects(); m_cleaningTemps = false; }); | ||
1315 | tempOnRezMS = Util.EnvironmentTickCountSubtract(tmpTempOnRezMS); | ||
1316 | } | ||
1317 | |||
1318 | if (Frame % m_update_events == 0) | ||
1319 | { | ||
1320 | int evMS = Util.EnvironmentTickCount(); | ||
1321 | UpdateEvents(); | ||
1322 | eventMS = Util.EnvironmentTickCountSubtract(evMS); ; | ||
1323 | } | ||
1324 | |||
1325 | // if (Frame % m_update_land == 0) | ||
1326 | // { | ||
1327 | // int ldMS = Util.EnvironmentTickCount(); | ||
1328 | // UpdateLand(); | ||
1329 | // landMS = Util.EnvironmentTickCountSubtract(ldMS); | ||
1330 | // } | ||
1331 | |||
1332 | if (Frame % m_update_backup == 0) | ||
1333 | { | ||
1334 | int backMS = Util.EnvironmentTickCount(); | ||
1335 | UpdateStorageBackup(); | ||
1336 | backupMS = Util.EnvironmentTickCountSubtract(backMS); | ||
1337 | } | ||
1338 | |||
1339 | if (Frame % m_update_terrain == 0) | ||
1340 | { | ||
1341 | int terMS = Util.EnvironmentTickCount(); | ||
1342 | UpdateTerrain(); | ||
1343 | terrainMS = Util.EnvironmentTickCountSubtract(terMS); | ||
1344 | } | ||
1345 | |||
1346 | //if (Frame % m_update_land == 0) | ||
1347 | //{ | ||
1348 | // int ldMS = Util.EnvironmentTickCount(); | ||
1349 | // UpdateLand(); | ||
1350 | // landMS = Util.EnvironmentTickCountSubtract(ldMS); | ||
1351 | //} | ||
1352 | |||
1353 | frameMS = Util.EnvironmentTickCountSubtract(tmpFrameMS); | ||
1354 | otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS; | ||
1355 | lastCompletedFrame = Util.EnvironmentTickCount(); | ||
1356 | |||
1357 | // if (Frame%m_update_avatars == 0) | ||
1358 | // UpdateInWorldTime(); | ||
1359 | StatsReporter.AddPhysicsFPS(physicsFPS); | ||
1360 | StatsReporter.AddTimeDilation(TimeDilation); | ||
1361 | StatsReporter.AddFPS(1); | ||
1362 | StatsReporter.SetRootAgents(m_sceneGraph.GetRootAgentCount()); | ||
1363 | StatsReporter.SetChildAgents(m_sceneGraph.GetChildAgentCount()); | ||
1364 | StatsReporter.SetObjects(m_sceneGraph.GetTotalObjectsCount()); | ||
1365 | StatsReporter.SetActiveObjects(m_sceneGraph.GetActiveObjectsCount()); | ||
1366 | StatsReporter.addFrameMS(frameMS); | ||
1367 | StatsReporter.addAgentMS(agentMS); | ||
1368 | StatsReporter.addPhysicsMS(physicsMS + physicsMS2); | ||
1369 | StatsReporter.addOtherMS(otherMS); | ||
1370 | StatsReporter.SetActiveScripts(m_sceneGraph.GetActiveScriptsCount()); | ||
1371 | StatsReporter.addScriptLines(m_sceneGraph.GetScriptLPS()); | ||
1372 | |||
1373 | if (LoginsDisabled && Frame == 20) | ||
1374 | { | ||
1375 | // m_log.DebugFormat("{0} {1} {2}", LoginsDisabled, m_sceneGraph.GetActiveScriptsCount(), LoginLock); | ||
1376 | |||
1377 | // In 99.9% of cases it is a bad idea to manually force garbage collection. However, | ||
1378 | // this is a rare case where we know we have just went through a long cycle of heap | ||
1379 | // allocations, and there is no more work to be done until someone logs in | ||
1380 | GC.Collect(); | ||
1381 | 1291 | ||
1382 | IConfig startupConfig = m_config.Configs["Startup"]; | 1292 | tmpAgentMS = Util.EnvironmentTickCount(); |
1383 | if (startupConfig == null || !startupConfig.GetBoolean("StartDisabled", false)) | 1293 | |
1294 | // Check if any objects have reached their targets | ||
1295 | CheckAtTargets(); | ||
1296 | |||
1297 | // Update SceneObjectGroups that have scheduled themselves for updates | ||
1298 | // Objects queue their updates onto all scene presences | ||
1299 | if (Frame % m_update_objects == 0) | ||
1300 | m_sceneGraph.UpdateObjectGroups(); | ||
1301 | |||
1302 | // Run through all ScenePresences looking for updates | ||
1303 | // Presence updates and queued object updates for each presence are sent to clients | ||
1304 | if (Frame % m_update_presences == 0) | ||
1305 | m_sceneGraph.UpdatePresences(); | ||
1306 | |||
1307 | // Coarse locations relate to positions of green dots on the mini-map (on a SecondLife client) | ||
1308 | if (Frame % m_update_coarse_locations == 0) | ||
1309 | { | ||
1310 | SceneGraph.GetCoarseLocations(out coarseLocations, out avatarUUIDs, 60); | ||
1311 | // Send coarse locations to clients | ||
1312 | ForEachScenePresence(delegate(ScenePresence presence) | ||
1313 | { | ||
1314 | presence.SendCoarseLocations(coarseLocations, avatarUUIDs); | ||
1315 | }); | ||
1316 | } | ||
1317 | |||
1318 | agentMS += Util.EnvironmentTickCountSubtract(tmpAgentMS); | ||
1319 | |||
1320 | // Delete temp-on-rez stuff | ||
1321 | if (Frame % m_update_temp_cleaning == 0 && !m_cleaningTemps) | ||
1322 | { | ||
1323 | tmpTempOnRezMS = Util.EnvironmentTickCount(); | ||
1324 | m_cleaningTemps = true; | ||
1325 | Util.FireAndForget(delegate { CleanTempObjects(); m_cleaningTemps = false; }); | ||
1326 | tempOnRezMS = Util.EnvironmentTickCountSubtract(tmpTempOnRezMS); | ||
1327 | } | ||
1328 | |||
1329 | if (Frame % m_update_events == 0) | ||
1330 | { | ||
1331 | evMS = Util.EnvironmentTickCount(); | ||
1332 | UpdateEvents(); | ||
1333 | eventMS = Util.EnvironmentTickCountSubtract(evMS); | ||
1334 | } | ||
1335 | |||
1336 | if (Frame % m_update_backup == 0) | ||
1337 | { | ||
1338 | backMS = Util.EnvironmentTickCount(); | ||
1339 | UpdateStorageBackup(); | ||
1340 | backupMS = Util.EnvironmentTickCountSubtract(backMS); | ||
1341 | } | ||
1342 | |||
1343 | if (Frame % m_update_terrain == 0) | ||
1384 | { | 1344 | { |
1385 | // This handles a case of a region having no scripts for the RegionReady module | 1345 | terMS = Util.EnvironmentTickCount(); |
1386 | if (m_sceneGraph.GetActiveScriptsCount() == 0) | 1346 | UpdateTerrain(); |
1347 | terrainMS = Util.EnvironmentTickCountSubtract(terMS); | ||
1348 | } | ||
1349 | |||
1350 | //if (Frame % m_update_land == 0) | ||
1351 | //{ | ||
1352 | // int ldMS = Util.EnvironmentTickCount(); | ||
1353 | // UpdateLand(); | ||
1354 | // landMS = Util.EnvironmentTickCountSubtract(ldMS); | ||
1355 | //} | ||
1356 | |||
1357 | frameMS = Util.EnvironmentTickCountSubtract(maintc); | ||
1358 | otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS; | ||
1359 | lastCompletedFrame = Util.EnvironmentTickCount(); | ||
1360 | |||
1361 | // if (Frame%m_update_avatars == 0) | ||
1362 | // UpdateInWorldTime(); | ||
1363 | StatsReporter.AddPhysicsFPS(physicsFPS); | ||
1364 | StatsReporter.AddTimeDilation(TimeDilation); | ||
1365 | StatsReporter.AddFPS(1); | ||
1366 | StatsReporter.SetRootAgents(m_sceneGraph.GetRootAgentCount()); | ||
1367 | StatsReporter.SetChildAgents(m_sceneGraph.GetChildAgentCount()); | ||
1368 | StatsReporter.SetObjects(m_sceneGraph.GetTotalObjectsCount()); | ||
1369 | StatsReporter.SetActiveObjects(m_sceneGraph.GetActiveObjectsCount()); | ||
1370 | |||
1371 | // frameMS currently records work frame times, not total frame times (work + any required sleep to | ||
1372 | // reach min frame time. | ||
1373 | StatsReporter.addFrameMS(frameMS); | ||
1374 | |||
1375 | StatsReporter.addAgentMS(agentMS); | ||
1376 | StatsReporter.addPhysicsMS(physicsMS + physicsMS2); | ||
1377 | StatsReporter.addOtherMS(otherMS); | ||
1378 | StatsReporter.SetActiveScripts(m_sceneGraph.GetActiveScriptsCount()); | ||
1379 | StatsReporter.addScriptLines(m_sceneGraph.GetScriptLPS()); | ||
1380 | |||
1381 | if (LoginsDisabled && Frame == 20) | ||
1382 | { | ||
1383 | // m_log.DebugFormat("{0} {1} {2}", LoginsDisabled, m_sceneGraph.GetActiveScriptsCount(), LoginLock); | ||
1384 | |||
1385 | // In 99.9% of cases it is a bad idea to manually force garbage collection. However, | ||
1386 | // this is a rare case where we know we have just went through a long cycle of heap | ||
1387 | // allocations, and there is no more work to be done until someone logs in | ||
1388 | GC.Collect(); | ||
1389 | |||
1390 | IConfig startupConfig = m_config.Configs["Startup"]; | ||
1391 | if (startupConfig == null || !startupConfig.GetBoolean("StartDisabled", false)) | ||
1387 | { | 1392 | { |
1388 | // need to be able to tell these have changed in RegionReady | 1393 | // This handles a case of a region having no scripts for the RegionReady module |
1389 | LoginLock = false; | 1394 | if (m_sceneGraph.GetActiveScriptsCount() == 0) |
1390 | EventManager.TriggerLoginsEnabled(RegionInfo.RegionName); | 1395 | { |
1396 | // need to be able to tell these have changed in RegionReady | ||
1397 | LoginLock = false; | ||
1398 | EventManager.TriggerLoginsEnabled(RegionInfo.RegionName); | ||
1399 | } | ||
1400 | m_log.DebugFormat("[REGION]: Enabling logins for {0}", RegionInfo.RegionName); | ||
1401 | |||
1402 | // For RegionReady lockouts | ||
1403 | if(LoginLock == false) | ||
1404 | { | ||
1405 | LoginsDisabled = false; | ||
1406 | } | ||
1407 | |||
1408 | m_sceneGridService.InformNeighborsThatRegionisUp(RequestModuleInterface<INeighbourService>(), RegionInfo); | ||
1391 | } | 1409 | } |
1392 | m_log.DebugFormat("[REGION]: Enabling logins for {0}", RegionInfo.RegionName); | 1410 | else |
1393 | |||
1394 | // For RegionReady lockouts | ||
1395 | if(LoginLock == false) | ||
1396 | { | 1411 | { |
1397 | LoginsDisabled = false; | 1412 | StartDisabled = true; |
1413 | LoginsDisabled = true; | ||
1398 | } | 1414 | } |
1399 | |||
1400 | m_sceneGridService.InformNeighborsThatRegionisUp(RequestModuleInterface<INeighbourService>(), RegionInfo); | ||
1401 | } | ||
1402 | else | ||
1403 | { | ||
1404 | StartDisabled = true; | ||
1405 | LoginsDisabled = true; | ||
1406 | } | 1415 | } |
1407 | } | 1416 | } |
1408 | } | 1417 | catch (Exception e) |
1409 | catch (Exception e) | 1418 | { |
1410 | { | 1419 | m_log.ErrorFormat( |
1411 | m_log.ErrorFormat( | 1420 | "[SCENE]: Failed on region {0} with exception {1}{2}", |
1412 | "[SCENE]: Failed on region {0} with exception {1}{2}", | 1421 | RegionInfo.RegionName, e.Message, e.StackTrace); |
1413 | RegionInfo.RegionName, e.Message, e.StackTrace); | 1422 | } |
1414 | } | 1423 | |
1415 | 1424 | EventManager.TriggerRegionHeartbeatEnd(this); | |
1416 | EventManager.TriggerRegionHeartbeatEnd(this); | ||
1417 | 1425 | ||
1418 | maintc = Util.EnvironmentTickCountSubtract(maintc); | 1426 | // Tell the watchdog that this thread is still alive |
1419 | maintc = (int)(MinFrameTime * 1000) - maintc; | 1427 | Watchdog.UpdateThread(); |
1420 | 1428 | ||
1429 | maintc = Util.EnvironmentTickCountSubtract(maintc); | ||
1430 | maintc = (int)(MinFrameTime * 1000) - maintc; | ||
1421 | 1431 | ||
1422 | m_lastUpdate = Util.EnvironmentTickCount(); | 1432 | m_lastUpdate = Util.EnvironmentTickCount(); |
1423 | m_firstHeartbeat = false; | 1433 | m_firstHeartbeat = false; |
1424 | 1434 | ||
1425 | if (maintc > 0) | 1435 | if (maintc > 0) |
1426 | Thread.Sleep(maintc); | 1436 | Thread.Sleep(maintc); |
1427 | 1437 | ||
1428 | // Tell the watchdog that this thread is still alive | 1438 | // if (frameMS > (int)(MinFrameTime * 1000)) |
1429 | Watchdog.UpdateThread(); | 1439 | // m_log.WarnFormat( |
1430 | } | 1440 | // "[SCENE]: Frame took {0} ms (desired max {1} ms) in {2}", |
1441 | // frameMS, | ||
1442 | // MinFrameTime * 1000, | ||
1443 | // RegionInfo.RegionName); | ||
1444 | } | ||
1445 | } | ||
1431 | 1446 | ||
1432 | public void AddGroupTarget(SceneObjectGroup grp) | 1447 | public void AddGroupTarget(SceneObjectGroup grp) |
1433 | { | 1448 | { |