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.cs231
1 files changed, 162 insertions, 69 deletions
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 44a738e..6ac7846 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -104,6 +104,11 @@ namespace OpenSim.Region.Framework.Scenes
104 public bool m_allowScriptCrossings; 104 public bool m_allowScriptCrossings;
105 public bool m_useFlySlow; 105 public bool m_useFlySlow;
106 106
107 /// <summary>
108 /// Temporarily setting to trigger appearance resends at 60 second intervals.
109 /// </summary>
110 public bool SendPeriodicAppearanceUpdates { get; set; }
111
107 protected float m_defaultDrawDistance = 255.0f; 112 protected float m_defaultDrawDistance = 255.0f;
108 public float DefaultDrawDistance 113 public float DefaultDrawDistance
109 { 114 {
@@ -172,6 +177,11 @@ namespace OpenSim.Region.Framework.Scenes
172 } 177 }
173 178
174 /// <summary> 179 /// <summary>
180 /// Current maintenance run number
181 /// </summary>
182 public uint MaintenanceRun { get; private set; }
183
184 /// <summary>
175 /// The minimum length of time in seconds that will be taken for a scene frame. If the frame takes less time then we 185 /// The minimum length of time in seconds that will be taken for a scene frame. If the frame takes less time then we
176 /// will sleep for the remaining period. 186 /// will sleep for the remaining period.
177 /// </summary> 187 /// </summary>
@@ -181,6 +191,11 @@ namespace OpenSim.Region.Framework.Scenes
181 /// </remarks> 191 /// </remarks>
182 public float MinFrameTime { get; private set; } 192 public float MinFrameTime { get; private set; }
183 193
194 /// <summary>
195 /// The minimum length of time in seconds that will be taken for a maintenance run.
196 /// </summary>
197 public float MinMaintenanceTime { get; private set; }
198
184 private int m_update_physics = 1; 199 private int m_update_physics = 1;
185 private int m_update_entitymovement = 1; 200 private int m_update_entitymovement = 1;
186 private int m_update_objects = 1; 201 private int m_update_objects = 1;
@@ -210,19 +225,22 @@ namespace OpenSim.Region.Framework.Scenes
210 225
211 public bool CombineRegions = false; 226 public bool CombineRegions = false;
212 /// <summary> 227 /// <summary>
228 /// Tick at which the last maintenance run occurred.
229 /// </summary>
230 private int m_lastMaintenanceTick;
231
232 /// <summary>
213 /// Signals whether temporary objects are currently being cleaned up. Needed because this is launched 233 /// Signals whether temporary objects are currently being cleaned up. Needed because this is launched
214 /// asynchronously from the update loop. 234 /// asynchronously from the update loop.
215 /// </summary> 235 /// </summary>
216 private bool m_cleaningTemps = false; 236 private bool m_cleaningTemps = false;
217 237
218 private Object m_heartbeatLock = new Object(); 238// private Object m_heartbeatLock = new Object();
219 239
220 // TODO: Possibly stop other classes being able to manipulate this directly. 240 // TODO: Possibly stop other classes being able to manipulate this directly.
221 private SceneGraph m_sceneGraph; 241 private SceneGraph m_sceneGraph;
222 private volatile int m_bordersLocked; 242 private volatile int m_bordersLocked;
223// private int m_RestartTimerCounter;
224 private readonly Timer m_restartTimer = new Timer(15000); // Wait before firing 243 private readonly Timer m_restartTimer = new Timer(15000); // Wait before firing
225// private int m_incrementsof15seconds;
226 private volatile bool m_backingup; 244 private volatile bool m_backingup;
227 private Dictionary<UUID, ReturnInfo> m_returns = new Dictionary<UUID, ReturnInfo>(); 245 private Dictionary<UUID, ReturnInfo> m_returns = new Dictionary<UUID, ReturnInfo>();
228 private Dictionary<UUID, SceneObjectGroup> m_groupsWithTargets = new Dictionary<UUID, SceneObjectGroup>(); 246 private Dictionary<UUID, SceneObjectGroup> m_groupsWithTargets = new Dictionary<UUID, SceneObjectGroup>();
@@ -230,16 +248,34 @@ namespace OpenSim.Region.Framework.Scenes
230 private bool m_physics_enabled = true; 248 private bool m_physics_enabled = true;
231 private bool m_scripts_enabled = true; 249 private bool m_scripts_enabled = true;
232 private string m_defaultScriptEngine; 250 private string m_defaultScriptEngine;
251
252 /// <summary>
253 /// Tick at which the last login occurred.
254 /// </summary>
233 private int m_LastLogin; 255 private int m_LastLogin;
234 private Thread HeartbeatThread = null;
235 private volatile bool shuttingdown;
236 256
237 private int m_lastUpdate;
238 private int m_lastIncoming; 257 private int m_lastIncoming;
239 private int m_lastOutgoing; 258 private int m_lastOutgoing;
240 private bool m_firstHeartbeat = true;
241 private int m_hbRestarts = 0; 259 private int m_hbRestarts = 0;
242 260
261
262 /// <summary>
263 /// Thread that runs the scene loop.
264 /// </summary>
265 private Thread m_heartbeatThread;
266
267 /// <summary>
268 /// True if these scene is in the process of shutting down or is shutdown.
269 /// </summary>
270 public bool ShuttingDown
271 {
272 get { return m_shuttingDown; }
273 }
274 private volatile bool m_shuttingDown;
275
276// private int m_lastUpdate;
277 private bool m_firstHeartbeat = true;
278
243 private UpdatePrioritizationSchemes m_priorityScheme = UpdatePrioritizationSchemes.Time; 279 private UpdatePrioritizationSchemes m_priorityScheme = UpdatePrioritizationSchemes.Time;
244 private bool m_reprioritizationEnabled = true; 280 private bool m_reprioritizationEnabled = true;
245 private double m_reprioritizationInterval = 5000.0; 281 private double m_reprioritizationInterval = 5000.0;
@@ -566,6 +602,7 @@ namespace OpenSim.Region.Framework.Scenes
566 { 602 {
567 m_config = config; 603 m_config = config;
568 MinFrameTime = 0.089f; 604 MinFrameTime = 0.089f;
605 MinMaintenanceTime = 1;
569 606
570 Random random = new Random(); 607 Random random = new Random();
571 608
@@ -577,7 +614,6 @@ namespace OpenSim.Region.Framework.Scenes
577 m_EstateDataService = estateDataService; 614 m_EstateDataService = estateDataService;
578 m_regionHandle = m_regInfo.RegionHandle; 615 m_regionHandle = m_regInfo.RegionHandle;
579 m_regionName = m_regInfo.RegionName; 616 m_regionName = m_regInfo.RegionName;
580 m_lastUpdate = Util.EnvironmentTickCount();
581 m_lastIncoming = 0; 617 m_lastIncoming = 0;
582 m_lastOutgoing = 0; 618 m_lastOutgoing = 0;
583 619
@@ -759,6 +795,7 @@ namespace OpenSim.Region.Framework.Scenes
759 m_update_presences = startupConfig.GetInt( "UpdateAgentsEveryNFrames", m_update_presences); 795 m_update_presences = startupConfig.GetInt( "UpdateAgentsEveryNFrames", m_update_presences);
760 m_update_terrain = startupConfig.GetInt( "UpdateTerrainEveryNFrames", m_update_terrain); 796 m_update_terrain = startupConfig.GetInt( "UpdateTerrainEveryNFrames", m_update_terrain);
761 m_update_temp_cleaning = startupConfig.GetInt( "UpdateTempCleaningEveryNFrames", m_update_temp_cleaning); 797 m_update_temp_cleaning = startupConfig.GetInt( "UpdateTempCleaningEveryNFrames", m_update_temp_cleaning);
798 SendPeriodicAppearanceUpdates = startupConfig.GetBoolean("SendPeriodicAppearanceUpdates", SendPeriodicAppearanceUpdates);
762 } 799 }
763 } 800 }
764 catch (Exception e) 801 catch (Exception e)
@@ -834,18 +871,13 @@ namespace OpenSim.Region.Framework.Scenes
834 871
835 m_permissions = new ScenePermissions(this); 872 m_permissions = new ScenePermissions(this);
836 873
837 m_lastUpdate = Util.EnvironmentTickCount(); 874// m_lastUpdate = Util.EnvironmentTickCount();
838 } 875 }
839 876
840 #endregion 877 #endregion
841 878
842 #region Startup / Close Methods 879 #region Startup / Close Methods
843 880
844 public bool ShuttingDown
845 {
846 get { return shuttingdown; }
847 }
848
849 /// <value> 881 /// <value>
850 /// The scene graph for this scene 882 /// The scene graph for this scene
851 /// </value> 883 /// </value>
@@ -1107,6 +1139,12 @@ namespace OpenSim.Region.Framework.Scenes
1107 m_physics_enabled = enablePhysics; 1139 m_physics_enabled = enablePhysics;
1108 } 1140 }
1109 1141
1142// if (options.ContainsKey("collisions"))
1143// {
1144// // TODO: Implement. If false, should stop objects colliding, though possibly should still allow
1145// // the avatar themselves to collide with the ground.
1146// }
1147
1110 if (options.ContainsKey("teleport")) 1148 if (options.ContainsKey("teleport"))
1111 { 1149 {
1112 bool enableTeleportDebugging; 1150 bool enableTeleportDebugging;
@@ -1158,8 +1196,7 @@ namespace OpenSim.Region.Framework.Scenes
1158 ForEachScenePresence(delegate(ScenePresence avatar) { avatar.ControllingClient.Close(); }); 1196 ForEachScenePresence(delegate(ScenePresence avatar) { avatar.ControllingClient.Close(); });
1159 1197
1160 // Stop updating the scene objects and agents. 1198 // Stop updating the scene objects and agents.
1161 //m_heartbeatTimer.Close(); 1199 m_shuttingDown = true;
1162 shuttingdown = true;
1163 1200
1164 m_log.Debug("[SCENE]: Persisting changed objects"); 1201 m_log.Debug("[SCENE]: Persisting changed objects");
1165 EventManager.TriggerSceneShuttingDown(this); 1202 EventManager.TriggerSceneShuttingDown(this);
@@ -1183,16 +1220,16 @@ namespace OpenSim.Region.Framework.Scenes
1183 } 1220 }
1184 1221
1185 /// <summary> 1222 /// <summary>
1186 /// Start the timer which triggers regular scene updates 1223 /// Start the scene
1187 /// </summary> 1224 /// </summary>
1188 public void StartTimer() 1225 public void Start()
1189 { 1226 {
1190// m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName); 1227// m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName);
1191 1228
1192 //m_heartbeatTimer.Enabled = true; 1229 //m_heartbeatTimer.Enabled = true;
1193 //m_heartbeatTimer.Interval = (int)(m_timespan * 1000); 1230 //m_heartbeatTimer.Interval = (int)(m_timespan * 1000);
1194 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat); 1231 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat);
1195 if (HeartbeatThread != null) 1232 if (m_heartbeatThread != null)
1196 { 1233 {
1197 m_hbRestarts++; 1234 m_hbRestarts++;
1198 if(m_hbRestarts > 10) 1235 if(m_hbRestarts > 10)
@@ -1208,13 +1245,13 @@ namespace OpenSim.Region.Framework.Scenes
1208//proc.WaitForExit(); 1245//proc.WaitForExit();
1209//Thread.Sleep(1000); 1246//Thread.Sleep(1000);
1210//Environment.Exit(1); 1247//Environment.Exit(1);
1211 HeartbeatThread.Abort(); 1248 m_heartbeatThread.Abort();
1212 Watchdog.AbortThread(HeartbeatThread.ManagedThreadId); 1249 Watchdog.AbortThread(m_heartbeatThread.ManagedThreadId);
1213 HeartbeatThread = null; 1250 m_heartbeatThread = null;
1214 } 1251 }
1215 m_lastUpdate = Util.EnvironmentTickCount(); 1252// m_lastUpdate = Util.EnvironmentTickCount();
1216 1253
1217 HeartbeatThread 1254 m_heartbeatThread
1218 = Watchdog.StartThread( 1255 = Watchdog.StartThread(
1219 Heartbeat, string.Format("Heartbeat ({0})", RegionInfo.RegionName), ThreadPriority.Normal, false, false); 1256 Heartbeat, string.Format("Heartbeat ({0})", RegionInfo.RegionName), ThreadPriority.Normal, false, false);
1220 } 1257 }
@@ -1245,34 +1282,107 @@ namespace OpenSim.Region.Framework.Scenes
1245 /// </summary> 1282 /// </summary>
1246 private void Heartbeat() 1283 private void Heartbeat()
1247 { 1284 {
1248 if (!Monitor.TryEnter(m_heartbeatLock)) 1285// if (!Monitor.TryEnter(m_heartbeatLock))
1249 { 1286// {
1250 Watchdog.RemoveThread(); 1287// Watchdog.RemoveThread();
1251 return; 1288// return;
1252 } 1289// }
1253 1290
1254 try 1291// try
1255 { 1292// {
1256 m_eventManager.TriggerOnRegionStarted(this);
1257 1293
1258 // The first frame can take a very long time due to physics actors being added on startup. Therefore, 1294 m_eventManager.TriggerOnRegionStarted(this);
1259 // don't turn on the watchdog alarm for this thread until the second frame, in order to prevent false
1260 // alarms for scenes with many objects.
1261 Update(1);
1262 Watchdog.GetCurrentThreadInfo().AlarmIfTimeout = true;
1263 1295
1264 while (!shuttingdown) 1296 // The first frame can take a very long time due to physics actors being added on startup. Therefore,
1265 Update(-1); 1297 // don't turn on the watchdog alarm for this thread until the second frame, in order to prevent false
1266 } 1298 // alarms for scenes with many objects.
1267 finally 1299 Update(1);
1268 { 1300
1269 Monitor.Pulse(m_heartbeatLock); 1301 Watchdog.StartThread(
1270 Monitor.Exit(m_heartbeatLock); 1302 Maintenance, string.Format("Maintenance ({0})", RegionInfo.RegionName), ThreadPriority.Normal, false, true);
1271 } 1303
1304 Watchdog.GetCurrentThreadInfo().AlarmIfTimeout = true;
1305 Update(-1);
1306
1307// m_lastUpdate = Util.EnvironmentTickCount();
1308// m_firstHeartbeat = false;
1309// }
1310// finally
1311// {
1312// Monitor.Pulse(m_heartbeatLock);
1313// Monitor.Exit(m_heartbeatLock);
1314// }
1315
1316 Watchdog.RemoveThread();
1317 }
1318
1319 private void Maintenance()
1320 {
1321 DoMaintenance(-1);
1272 1322
1273 Watchdog.RemoveThread(); 1323 Watchdog.RemoveThread();
1274 } 1324 }
1275 1325
1326 public void DoMaintenance(int runs)
1327 {
1328 long? endRun = null;
1329 int runtc;
1330 int previousMaintenanceTick;
1331
1332 if (runs >= 0)
1333 endRun = MaintenanceRun + runs;
1334
1335 List<Vector3> coarseLocations;
1336 List<UUID> avatarUUIDs;
1337
1338 while (!m_shuttingDown && (endRun == null || MaintenanceRun < endRun))
1339 {
1340 runtc = Util.EnvironmentTickCount();
1341 ++MaintenanceRun;
1342
1343 // Coarse locations relate to positions of green dots on the mini-map (on a SecondLife client)
1344 if (MaintenanceRun % (m_update_coarse_locations / 10) == 0)
1345 {
1346 SceneGraph.GetCoarseLocations(out coarseLocations, out avatarUUIDs, 60);
1347 // Send coarse locations to clients
1348 ForEachScenePresence(delegate(ScenePresence presence)
1349 {
1350 presence.SendCoarseLocations(coarseLocations, avatarUUIDs);
1351 });
1352 }
1353
1354 if (SendPeriodicAppearanceUpdates && MaintenanceRun % 60 == 0)
1355 {
1356// m_log.DebugFormat("[SCENE]: Sending periodic appearance updates");
1357
1358 if (AvatarFactory != null)
1359 {
1360 ForEachRootScenePresence(sp => AvatarFactory.SendAppearance(sp.UUID));
1361 }
1362 }
1363
1364 Watchdog.UpdateThread();
1365
1366 previousMaintenanceTick = m_lastMaintenanceTick;
1367 m_lastMaintenanceTick = Util.EnvironmentTickCount();
1368 runtc = Util.EnvironmentTickCountSubtract(m_lastMaintenanceTick, runtc);
1369 runtc = (int)(MinMaintenanceTime * 1000) - runtc;
1370
1371 if (runtc > 0)
1372 Thread.Sleep(runtc);
1373
1374 // Optionally warn if a frame takes double the amount of time that it should.
1375 if (DebugUpdates
1376 && Util.EnvironmentTickCountSubtract(
1377 m_lastMaintenanceTick, previousMaintenanceTick) > (int)(MinMaintenanceTime * 1000 * 2))
1378 m_log.WarnFormat(
1379 "[SCENE]: Maintenance took {0} ms (desired max {1} ms) in {2}",
1380 Util.EnvironmentTickCountSubtract(m_lastMaintenanceTick, previousMaintenanceTick),
1381 MinMaintenanceTime * 1000,
1382 RegionInfo.RegionName);
1383 }
1384 }
1385
1276 public override void Update(int frames) 1386 public override void Update(int frames)
1277 { 1387 {
1278 long? endFrame = null; 1388 long? endFrame = null;
@@ -1284,10 +1394,8 @@ namespace OpenSim.Region.Framework.Scenes
1284 int tmpPhysicsMS, tmpPhysicsMS2, tmpAgentMS, tmpTempOnRezMS, evMS, backMS, terMS; 1394 int tmpPhysicsMS, tmpPhysicsMS2, tmpAgentMS, tmpTempOnRezMS, evMS, backMS, terMS;
1285 int previousFrameTick; 1395 int previousFrameTick;
1286 int maintc; 1396 int maintc;
1287 List<Vector3> coarseLocations;
1288 List<UUID> avatarUUIDs;
1289 1397
1290 while (!shuttingdown && (endFrame == null || Frame < endFrame)) 1398 while (!m_shuttingDown && (endFrame == null || Frame < endFrame))
1291 { 1399 {
1292 maintc = Util.EnvironmentTickCount(); 1400 maintc = Util.EnvironmentTickCount();
1293 ++Frame; 1401 ++Frame;
@@ -1337,17 +1445,6 @@ namespace OpenSim.Region.Framework.Scenes
1337 if (Frame % m_update_presences == 0) 1445 if (Frame % m_update_presences == 0)
1338 m_sceneGraph.UpdatePresences(); 1446 m_sceneGraph.UpdatePresences();
1339 1447
1340 // Coarse locations relate to positions of green dots on the mini-map (on a SecondLife client)
1341 if (Frame % m_update_coarse_locations == 0)
1342 {
1343 SceneGraph.GetCoarseLocations(out coarseLocations, out avatarUUIDs, 60);
1344 // Send coarse locations to clients
1345 ForEachScenePresence(delegate(ScenePresence presence)
1346 {
1347 presence.SendCoarseLocations(coarseLocations, avatarUUIDs);
1348 });
1349 }
1350
1351 agentMS += Util.EnvironmentTickCountSubtract(tmpAgentMS); 1448 agentMS += Util.EnvironmentTickCountSubtract(tmpAgentMS);
1352 1449
1353 // Delete temp-on-rez stuff 1450 // Delete temp-on-rez stuff
@@ -1455,7 +1552,6 @@ namespace OpenSim.Region.Framework.Scenes
1455 1552
1456 EventManager.TriggerRegionHeartbeatEnd(this); 1553 EventManager.TriggerRegionHeartbeatEnd(this);
1457 1554
1458 // Tell the watchdog that this thread is still alive
1459 Watchdog.UpdateThread(); 1555 Watchdog.UpdateThread();
1460 1556
1461 previousFrameTick = m_lastFrameTick; 1557 previousFrameTick = m_lastFrameTick;
@@ -1463,15 +1559,11 @@ namespace OpenSim.Region.Framework.Scenes
1463 maintc = Util.EnvironmentTickCountSubtract(m_lastFrameTick, maintc); 1559 maintc = Util.EnvironmentTickCountSubtract(m_lastFrameTick, maintc);
1464 maintc = (int)(MinFrameTime * 1000) - maintc; 1560 maintc = (int)(MinFrameTime * 1000) - maintc;
1465 1561
1466 m_lastUpdate = Util.EnvironmentTickCount();
1467 m_firstHeartbeat = false; 1562 m_firstHeartbeat = false;
1468 1563
1469 if (maintc > 0) 1564 if (maintc > 0)
1470 Thread.Sleep(maintc); 1565 Thread.Sleep(maintc);
1471 1566
1472 m_lastUpdate = Util.EnvironmentTickCount();
1473 m_firstHeartbeat = false;
1474
1475 // Optionally warn if a frame takes double the amount of time that it should. 1567 // Optionally warn if a frame takes double the amount of time that it should.
1476 if (DebugUpdates 1568 if (DebugUpdates
1477 && Util.EnvironmentTickCountSubtract( 1569 && Util.EnvironmentTickCountSubtract(
@@ -2662,7 +2754,6 @@ namespace OpenSim.Region.Framework.Scenes
2662 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; 2754 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0;
2663 2755
2664 CheckHeartbeat(); 2756 CheckHeartbeat();
2665 ScenePresence presence;
2666 2757
2667 ScenePresence sp = GetScenePresence(client.AgentId); 2758 ScenePresence sp = GetScenePresence(client.AgentId);
2668 2759
@@ -3253,7 +3344,7 @@ namespace OpenSim.Region.Framework.Scenes
3253 3344
3254 public override void RemoveClient(UUID agentID, bool closeChildAgents) 3345 public override void RemoveClient(UUID agentID, bool closeChildAgents)
3255 { 3346 {
3256 CheckHeartbeat(); 3347// CheckHeartbeat();
3257 bool isChildAgent = false; 3348 bool isChildAgent = false;
3258 ScenePresence avatar = GetScenePresence(agentID); 3349 ScenePresence avatar = GetScenePresence(agentID);
3259 if (avatar != null) 3350 if (avatar != null)
@@ -4700,7 +4791,7 @@ namespace OpenSim.Region.Framework.Scenes
4700 4791
4701 int health=1; // Start at 1, means we're up 4792 int health=1; // Start at 1, means we're up
4702 4793
4703 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) < 1000) 4794 if ((Util.EnvironmentTickCountSubtract(m_lastFrameTick)) < 1000)
4704 { 4795 {
4705 health+=1; 4796 health+=1;
4706 flags |= 1; 4797 flags |= 1;
@@ -4737,6 +4828,8 @@ Environment.Exit(1);
4737 // 4828 //
4738 if (Util.EnvironmentTickCountSubtract(m_LastLogin) < 240000) 4829 if (Util.EnvironmentTickCountSubtract(m_LastLogin) < 240000)
4739 health++; 4830 health++;
4831 else
4832 return health;
4740 4833
4741 return health; 4834 return health;
4742 } 4835 }
@@ -4929,8 +5022,8 @@ Environment.Exit(1);
4929 if (m_firstHeartbeat) 5022 if (m_firstHeartbeat)
4930 return; 5023 return;
4931 5024
4932 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) > 5000) 5025 if ((Util.EnvironmentTickCountSubtract(m_lastFrameTick)) > 5000)
4933 StartTimer(); 5026 Start();
4934 } 5027 }
4935 5028
4936 public override ISceneObject DeserializeObject(string representation) 5029 public override ISceneObject DeserializeObject(string representation)