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