diff options
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/Scene.cs | 710 |
1 files changed, 425 insertions, 285 deletions
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 292c81f..0b31e0c 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs | |||
@@ -65,7 +65,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
65 | #region Fields | 65 | #region Fields |
66 | 66 | ||
67 | public bool EmergencyMonitoring = false; | 67 | public bool EmergencyMonitoring = false; |
68 | public bool DEBUG = false; | 68 | |
69 | /// <summary> | ||
70 | /// Show debug information about teleports. | ||
71 | /// </summary> | ||
72 | public bool DebugTeleporting { get; private set; } | ||
73 | |||
74 | /// <summary> | ||
75 | /// Show debug information about the scene loop. | ||
76 | /// </summary> | ||
77 | public bool DebugUpdates { get; private set; } | ||
69 | 78 | ||
70 | public SynchronizeSceneHandler SynchronizeScene; | 79 | public SynchronizeSceneHandler SynchronizeScene; |
71 | public SimStatsReporter StatsReporter; | 80 | public SimStatsReporter StatsReporter; |
@@ -95,6 +104,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
95 | public bool m_allowScriptCrossings; | 104 | public bool m_allowScriptCrossings; |
96 | public bool m_useFlySlow; | 105 | public bool m_useFlySlow; |
97 | 106 | ||
107 | /// <summary> | ||
108 | /// Temporarily setting to trigger appearance resends at 60 second intervals. | ||
109 | /// </summary> | ||
110 | public bool SendPeriodicAppearanceUpdates { get; set; } | ||
111 | |||
98 | protected float m_defaultDrawDistance = 255.0f; | 112 | protected float m_defaultDrawDistance = 255.0f; |
99 | public float DefaultDrawDistance | 113 | public float DefaultDrawDistance |
100 | { | 114 | { |
@@ -160,6 +174,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
160 | } | 174 | } |
161 | 175 | ||
162 | /// <summary> | 176 | /// <summary> |
177 | /// Current maintenance run number | ||
178 | /// </summary> | ||
179 | public uint MaintenanceRun { get; private set; } | ||
180 | |||
181 | /// <summary> | ||
163 | /// The minimum length of time in seconds that will be taken for a scene frame. If the frame takes less time then we | 182 | /// The minimum length of time in seconds that will be taken for a scene frame. If the frame takes less time then we |
164 | /// will sleep for the remaining period. | 183 | /// will sleep for the remaining period. |
165 | /// </summary> | 184 | /// </summary> |
@@ -169,6 +188,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
169 | /// </remarks> | 188 | /// </remarks> |
170 | public float MinFrameTime { get; private set; } | 189 | public float MinFrameTime { get; private set; } |
171 | 190 | ||
191 | /// <summary> | ||
192 | /// The minimum length of time in seconds that will be taken for a maintenance run. | ||
193 | /// </summary> | ||
194 | public float MinMaintenanceTime { get; private set; } | ||
195 | |||
172 | private int m_update_physics = 1; | 196 | private int m_update_physics = 1; |
173 | private int m_update_entitymovement = 1; | 197 | private int m_update_entitymovement = 1; |
174 | private int m_update_objects = 1; | 198 | private int m_update_objects = 1; |
@@ -190,7 +214,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
190 | private int backupMS; | 214 | private int backupMS; |
191 | private int terrainMS; | 215 | private int terrainMS; |
192 | private int landMS; | 216 | private int landMS; |
193 | private int lastCompletedFrame; | 217 | |
218 | /// <summary> | ||
219 | /// Tick at which the last frame was processed. | ||
220 | /// </summary> | ||
221 | private int m_lastFrameTick; | ||
222 | |||
223 | /// <summary> | ||
224 | /// Tick at which the last maintenance run occurred. | ||
225 | /// </summary> | ||
226 | private int m_lastMaintenanceTick; | ||
194 | 227 | ||
195 | /// <summary> | 228 | /// <summary> |
196 | /// Signals whether temporary objects are currently being cleaned up. Needed because this is launched | 229 | /// Signals whether temporary objects are currently being cleaned up. Needed because this is launched |
@@ -198,14 +231,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
198 | /// </summary> | 231 | /// </summary> |
199 | private bool m_cleaningTemps = false; | 232 | private bool m_cleaningTemps = false; |
200 | 233 | ||
201 | private Object m_heartbeatLock = new Object(); | 234 | // private Object m_heartbeatLock = new Object(); |
202 | 235 | ||
203 | // TODO: Possibly stop other classes being able to manipulate this directly. | 236 | // TODO: Possibly stop other classes being able to manipulate this directly. |
204 | private SceneGraph m_sceneGraph; | 237 | private SceneGraph m_sceneGraph; |
205 | private volatile int m_bordersLocked; | 238 | private volatile int m_bordersLocked; |
206 | // private int m_RestartTimerCounter; | ||
207 | private readonly Timer m_restartTimer = new Timer(15000); // Wait before firing | 239 | private readonly Timer m_restartTimer = new Timer(15000); // Wait before firing |
208 | // private int m_incrementsof15seconds; | ||
209 | private volatile bool m_backingup; | 240 | private volatile bool m_backingup; |
210 | private Dictionary<UUID, ReturnInfo> m_returns = new Dictionary<UUID, ReturnInfo>(); | 241 | private Dictionary<UUID, ReturnInfo> m_returns = new Dictionary<UUID, ReturnInfo>(); |
211 | private Dictionary<UUID, SceneObjectGroup> m_groupsWithTargets = new Dictionary<UUID, SceneObjectGroup>(); | 242 | private Dictionary<UUID, SceneObjectGroup> m_groupsWithTargets = new Dictionary<UUID, SceneObjectGroup>(); |
@@ -213,14 +244,28 @@ namespace OpenSim.Region.Framework.Scenes | |||
213 | private bool m_physics_enabled = true; | 244 | private bool m_physics_enabled = true; |
214 | private bool m_scripts_enabled = true; | 245 | private bool m_scripts_enabled = true; |
215 | private string m_defaultScriptEngine; | 246 | private string m_defaultScriptEngine; |
247 | |||
248 | /// <summary> | ||
249 | /// Tick at which the last login occurred. | ||
250 | /// </summary> | ||
216 | private int m_LastLogin; | 251 | private int m_LastLogin; |
217 | private Thread HeartbeatThread; | ||
218 | private volatile bool shuttingdown; | ||
219 | 252 | ||
220 | private int m_lastUpdate; | 253 | /// <summary> |
221 | private bool m_firstHeartbeat = true; | 254 | /// Thread that runs the scene loop. |
255 | /// </summary> | ||
256 | private Thread m_heartbeatThread; | ||
222 | 257 | ||
223 | private object m_deleting_scene_object = new object(); | 258 | /// <summary> |
259 | /// True if these scene is in the process of shutting down or is shutdown. | ||
260 | /// </summary> | ||
261 | public bool ShuttingDown | ||
262 | { | ||
263 | get { return m_shuttingDown; } | ||
264 | } | ||
265 | private volatile bool m_shuttingDown; | ||
266 | |||
267 | // private int m_lastUpdate; | ||
268 | // private bool m_firstHeartbeat = true; | ||
224 | 269 | ||
225 | private UpdatePrioritizationSchemes m_priorityScheme = UpdatePrioritizationSchemes.Time; | 270 | private UpdatePrioritizationSchemes m_priorityScheme = UpdatePrioritizationSchemes.Time; |
226 | private bool m_reprioritizationEnabled = true; | 271 | private bool m_reprioritizationEnabled = true; |
@@ -466,7 +511,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
466 | public int MonitorBackupTime { get { return backupMS; } } | 511 | public int MonitorBackupTime { get { return backupMS; } } |
467 | public int MonitorTerrainTime { get { return terrainMS; } } | 512 | public int MonitorTerrainTime { get { return terrainMS; } } |
468 | public int MonitorLandTime { get { return landMS; } } | 513 | public int MonitorLandTime { get { return landMS; } } |
469 | public int MonitorLastFrameTick { get { return lastCompletedFrame; } } | 514 | public int MonitorLastFrameTick { get { return m_lastFrameTick; } } |
470 | 515 | ||
471 | public UpdatePrioritizationSchemes UpdatePrioritizationScheme { get { return m_priorityScheme; } } | 516 | public UpdatePrioritizationSchemes UpdatePrioritizationScheme { get { return m_priorityScheme; } } |
472 | public bool IsReprioritizationEnabled { get { return m_reprioritizationEnabled; } } | 517 | public bool IsReprioritizationEnabled { get { return m_reprioritizationEnabled; } } |
@@ -535,6 +580,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
535 | { | 580 | { |
536 | m_config = config; | 581 | m_config = config; |
537 | MinFrameTime = 0.089f; | 582 | MinFrameTime = 0.089f; |
583 | MinMaintenanceTime = 1; | ||
538 | 584 | ||
539 | Random random = new Random(); | 585 | Random random = new Random(); |
540 | 586 | ||
@@ -596,7 +642,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
596 | 642 | ||
597 | #endregion Region Settings | 643 | #endregion Region Settings |
598 | 644 | ||
599 | MainConsole.Instance.Commands.AddCommand("region", false, "reload estate", | 645 | MainConsole.Instance.Commands.AddCommand("Estates", false, "reload estate", |
600 | "reload estate", | 646 | "reload estate", |
601 | "Reload the estate data", HandleReloadEstate); | 647 | "Reload the estate data", HandleReloadEstate); |
602 | 648 | ||
@@ -628,10 +674,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
628 | 674 | ||
629 | #region Region Config | 675 | #region Region Config |
630 | 676 | ||
631 | try | 677 | // Region config overrides global config |
678 | // | ||
679 | if (m_config.Configs["Startup"] != null) | ||
632 | { | 680 | { |
633 | // Region config overrides global config | ||
634 | // | ||
635 | IConfig startupConfig = m_config.Configs["Startup"]; | 681 | IConfig startupConfig = m_config.Configs["Startup"]; |
636 | 682 | ||
637 | m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance",m_defaultDrawDistance); | 683 | m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance",m_defaultDrawDistance); |
@@ -720,47 +766,42 @@ namespace OpenSim.Region.Framework.Scenes | |||
720 | m_update_presences = startupConfig.GetInt( "UpdateAgentsEveryNFrames", m_update_presences); | 766 | m_update_presences = startupConfig.GetInt( "UpdateAgentsEveryNFrames", m_update_presences); |
721 | m_update_terrain = startupConfig.GetInt( "UpdateTerrainEveryNFrames", m_update_terrain); | 767 | m_update_terrain = startupConfig.GetInt( "UpdateTerrainEveryNFrames", m_update_terrain); |
722 | m_update_temp_cleaning = startupConfig.GetInt( "UpdateTempCleaningEveryNFrames", m_update_temp_cleaning); | 768 | m_update_temp_cleaning = startupConfig.GetInt( "UpdateTempCleaningEveryNFrames", m_update_temp_cleaning); |
723 | } | 769 | |
724 | catch | 770 | SendPeriodicAppearanceUpdates = startupConfig.GetBoolean("SendPeriodicAppearanceUpdates", SendPeriodicAppearanceUpdates); |
725 | { | ||
726 | m_log.Warn("[SCENE]: Failed to load StartupConfig"); | ||
727 | } | 771 | } |
728 | 772 | ||
729 | #endregion Region Config | 773 | #endregion Region Config |
730 | 774 | ||
731 | #region Interest Management | 775 | #region Interest Management |
732 | 776 | ||
733 | if (m_config != null) | 777 | IConfig interestConfig = m_config.Configs["InterestManagement"]; |
778 | if (interestConfig != null) | ||
734 | { | 779 | { |
735 | IConfig interestConfig = m_config.Configs["InterestManagement"]; | 780 | string update_prioritization_scheme = interestConfig.GetString("UpdatePrioritizationScheme", "Time").Trim().ToLower(); |
736 | if (interestConfig != null) | ||
737 | { | ||
738 | string update_prioritization_scheme = interestConfig.GetString("UpdatePrioritizationScheme", "Time").Trim().ToLower(); | ||
739 | 781 | ||
740 | try | 782 | try |
741 | { | 783 | { |
742 | m_priorityScheme = (UpdatePrioritizationSchemes)Enum.Parse(typeof(UpdatePrioritizationSchemes), update_prioritization_scheme, true); | 784 | m_priorityScheme = (UpdatePrioritizationSchemes)Enum.Parse(typeof(UpdatePrioritizationSchemes), update_prioritization_scheme, true); |
743 | } | 785 | } |
744 | catch (Exception) | 786 | catch (Exception) |
745 | { | 787 | { |
746 | m_log.Warn("[PRIORITIZER]: UpdatePrioritizationScheme was not recognized, setting to default prioritizer Time"); | 788 | m_log.Warn("[PRIORITIZER]: UpdatePrioritizationScheme was not recognized, setting to default prioritizer Time"); |
747 | m_priorityScheme = UpdatePrioritizationSchemes.Time; | 789 | m_priorityScheme = UpdatePrioritizationSchemes.Time; |
748 | } | ||
749 | |||
750 | m_reprioritizationEnabled = interestConfig.GetBoolean("ReprioritizationEnabled", true); | ||
751 | m_reprioritizationInterval = interestConfig.GetDouble("ReprioritizationInterval", 5000.0); | ||
752 | m_rootReprioritizationDistance = interestConfig.GetDouble("RootReprioritizationDistance", 10.0); | ||
753 | m_childReprioritizationDistance = interestConfig.GetDouble("ChildReprioritizationDistance", 20.0); | ||
754 | } | 790 | } |
791 | |||
792 | m_reprioritizationEnabled = interestConfig.GetBoolean("ReprioritizationEnabled", true); | ||
793 | m_reprioritizationInterval = interestConfig.GetDouble("ReprioritizationInterval", 5000.0); | ||
794 | m_rootReprioritizationDistance = interestConfig.GetDouble("RootReprioritizationDistance", 10.0); | ||
795 | m_childReprioritizationDistance = interestConfig.GetDouble("ChildReprioritizationDistance", 20.0); | ||
755 | } | 796 | } |
756 | 797 | ||
757 | m_log.InfoFormat("[SCENE]: Using the {0} prioritization scheme", m_priorityScheme); | 798 | m_log.DebugFormat("[SCENE]: Using the {0} prioritization scheme", m_priorityScheme); |
758 | 799 | ||
759 | #endregion Interest Management | 800 | #endregion Interest Management |
760 | 801 | ||
761 | StatsReporter = new SimStatsReporter(this); | 802 | StatsReporter = new SimStatsReporter(this); |
762 | StatsReporter.OnSendStatsResult += SendSimStatsPackets; | 803 | StatsReporter.OnSendStatsResult += SendSimStatsPackets; |
763 | StatsReporter.OnStatsIncorrect += m_sceneGraph.RecalculateStats; | 804 | StatsReporter.OnStatsIncorrect += m_sceneGraph.RecalculateStats; |
764 | } | 805 | } |
765 | 806 | ||
766 | /// <summary> | 807 | /// <summary> |
@@ -797,18 +838,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
797 | 838 | ||
798 | m_permissions = new ScenePermissions(this); | 839 | m_permissions = new ScenePermissions(this); |
799 | 840 | ||
800 | m_lastUpdate = Util.EnvironmentTickCount(); | 841 | // m_lastUpdate = Util.EnvironmentTickCount(); |
801 | } | 842 | } |
802 | 843 | ||
803 | #endregion | 844 | #endregion |
804 | 845 | ||
805 | #region Startup / Close Methods | 846 | #region Startup / Close Methods |
806 | 847 | ||
807 | public bool ShuttingDown | ||
808 | { | ||
809 | get { return shuttingdown; } | ||
810 | } | ||
811 | |||
812 | /// <value> | 848 | /// <value> |
813 | /// The scene graph for this scene | 849 | /// The scene graph for this scene |
814 | /// </value> | 850 | /// </value> |
@@ -1025,44 +1061,72 @@ namespace OpenSim.Region.Framework.Scenes | |||
1025 | } | 1061 | } |
1026 | } | 1062 | } |
1027 | 1063 | ||
1028 | public void SetSceneCoreDebug(bool ScriptEngine, bool CollisionEvents, bool PhysicsEngine) | 1064 | public void SetSceneCoreDebug(Dictionary<string, string> options) |
1029 | { | 1065 | { |
1030 | if (m_scripts_enabled != !ScriptEngine) | 1066 | if (options.ContainsKey("scripting")) |
1031 | { | 1067 | { |
1032 | if (ScriptEngine) | 1068 | bool enableScripts = true; |
1069 | if (bool.TryParse(options["scripting"], out enableScripts) && m_scripts_enabled != enableScripts) | ||
1033 | { | 1070 | { |
1034 | m_log.Info("Stopping all Scripts in Scene"); | 1071 | if (!enableScripts) |
1035 | |||
1036 | EntityBase[] entities = Entities.GetEntities(); | ||
1037 | foreach (EntityBase ent in entities) | ||
1038 | { | 1072 | { |
1039 | if (ent is SceneObjectGroup) | 1073 | m_log.Info("Stopping all Scripts in Scene"); |
1040 | ((SceneObjectGroup)ent).RemoveScriptInstances(false); | 1074 | |
1075 | EntityBase[] entities = Entities.GetEntities(); | ||
1076 | foreach (EntityBase ent in entities) | ||
1077 | { | ||
1078 | if (ent is SceneObjectGroup) | ||
1079 | ((SceneObjectGroup)ent).RemoveScriptInstances(false); | ||
1080 | } | ||
1041 | } | 1081 | } |
1042 | } | 1082 | else |
1043 | else | ||
1044 | { | ||
1045 | m_log.Info("Starting all Scripts in Scene"); | ||
1046 | |||
1047 | EntityBase[] entities = Entities.GetEntities(); | ||
1048 | foreach (EntityBase ent in entities) | ||
1049 | { | 1083 | { |
1050 | if (ent is SceneObjectGroup) | 1084 | m_log.Info("Starting all Scripts in Scene"); |
1085 | |||
1086 | EntityBase[] entities = Entities.GetEntities(); | ||
1087 | foreach (EntityBase ent in entities) | ||
1051 | { | 1088 | { |
1052 | SceneObjectGroup sog = (SceneObjectGroup)ent; | 1089 | if (ent is SceneObjectGroup) |
1053 | sog.CreateScriptInstances(0, false, DefaultScriptEngine, 0); | 1090 | { |
1054 | sog.ResumeScripts(); | 1091 | SceneObjectGroup sog = (SceneObjectGroup)ent; |
1092 | sog.CreateScriptInstances(0, false, DefaultScriptEngine, 0); | ||
1093 | sog.ResumeScripts(); | ||
1094 | } | ||
1055 | } | 1095 | } |
1056 | } | 1096 | } |
1097 | |||
1098 | m_scripts_enabled = enableScripts; | ||
1057 | } | 1099 | } |
1100 | } | ||
1101 | |||
1102 | if (options.ContainsKey("physics")) | ||
1103 | { | ||
1104 | bool enablePhysics; | ||
1105 | if (bool.TryParse(options["physics"], out enablePhysics)) | ||
1106 | m_physics_enabled = enablePhysics; | ||
1107 | } | ||
1108 | |||
1109 | // if (options.ContainsKey("collisions")) | ||
1110 | // { | ||
1111 | // // TODO: Implement. If false, should stop objects colliding, though possibly should still allow | ||
1112 | // // the avatar themselves to collide with the ground. | ||
1113 | // } | ||
1058 | 1114 | ||
1059 | m_scripts_enabled = !ScriptEngine; | 1115 | if (options.ContainsKey("teleport")) |
1060 | m_log.Info("[TOTEDD]: Here is the method to trigger disabling of the scripting engine"); | 1116 | { |
1117 | bool enableTeleportDebugging; | ||
1118 | if (bool.TryParse(options["teleport"], out enableTeleportDebugging)) | ||
1119 | DebugTeleporting = enableTeleportDebugging; | ||
1061 | } | 1120 | } |
1062 | 1121 | ||
1063 | if (m_physics_enabled != !PhysicsEngine) | 1122 | if (options.ContainsKey("updates")) |
1064 | { | 1123 | { |
1065 | m_physics_enabled = !PhysicsEngine; | 1124 | bool enableUpdateDebugging; |
1125 | if (bool.TryParse(options["updates"], out enableUpdateDebugging)) | ||
1126 | { | ||
1127 | DebugUpdates = enableUpdateDebugging; | ||
1128 | GcNotify.Enabled = DebugUpdates; | ||
1129 | } | ||
1066 | } | 1130 | } |
1067 | } | 1131 | } |
1068 | 1132 | ||
@@ -1076,6 +1140,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
1076 | { | 1140 | { |
1077 | m_log.InfoFormat("[SCENE]: Closing down the single simulator: {0}", RegionInfo.RegionName); | 1141 | m_log.InfoFormat("[SCENE]: Closing down the single simulator: {0}", RegionInfo.RegionName); |
1078 | 1142 | ||
1143 | StatsReporter.Close(); | ||
1144 | |||
1079 | m_restartTimer.Stop(); | 1145 | m_restartTimer.Stop(); |
1080 | m_restartTimer.Close(); | 1146 | m_restartTimer.Close(); |
1081 | 1147 | ||
@@ -1097,8 +1163,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1097 | ForEachScenePresence(delegate(ScenePresence avatar) { avatar.ControllingClient.Close(); }); | 1163 | ForEachScenePresence(delegate(ScenePresence avatar) { avatar.ControllingClient.Close(); }); |
1098 | 1164 | ||
1099 | // Stop updating the scene objects and agents. | 1165 | // Stop updating the scene objects and agents. |
1100 | //m_heartbeatTimer.Close(); | 1166 | m_shuttingDown = true; |
1101 | shuttingdown = true; | ||
1102 | 1167 | ||
1103 | m_log.Debug("[SCENE]: Persisting changed objects"); | 1168 | m_log.Debug("[SCENE]: Persisting changed objects"); |
1104 | EventManager.TriggerSceneShuttingDown(this); | 1169 | EventManager.TriggerSceneShuttingDown(this); |
@@ -1122,23 +1187,23 @@ namespace OpenSim.Region.Framework.Scenes | |||
1122 | } | 1187 | } |
1123 | 1188 | ||
1124 | /// <summary> | 1189 | /// <summary> |
1125 | /// Start the timer which triggers regular scene updates | 1190 | /// Start the scene |
1126 | /// </summary> | 1191 | /// </summary> |
1127 | public void StartTimer() | 1192 | public void Start() |
1128 | { | 1193 | { |
1129 | // m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName); | 1194 | // m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName); |
1130 | 1195 | ||
1131 | //m_heartbeatTimer.Enabled = true; | 1196 | //m_heartbeatTimer.Enabled = true; |
1132 | //m_heartbeatTimer.Interval = (int)(m_timespan * 1000); | 1197 | //m_heartbeatTimer.Interval = (int)(m_timespan * 1000); |
1133 | //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat); | 1198 | //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat); |
1134 | if (HeartbeatThread != null) | 1199 | if (m_heartbeatThread != null) |
1135 | { | 1200 | { |
1136 | HeartbeatThread.Abort(); | 1201 | m_heartbeatThread.Abort(); |
1137 | HeartbeatThread = null; | 1202 | m_heartbeatThread = null; |
1138 | } | 1203 | } |
1139 | m_lastUpdate = Util.EnvironmentTickCount(); | 1204 | // m_lastUpdate = Util.EnvironmentTickCount(); |
1140 | 1205 | ||
1141 | HeartbeatThread | 1206 | m_heartbeatThread |
1142 | = Watchdog.StartThread( | 1207 | = Watchdog.StartThread( |
1143 | Heartbeat, string.Format("Heartbeat ({0})", RegionInfo.RegionName), ThreadPriority.Normal, false, false); | 1208 | Heartbeat, string.Format("Heartbeat ({0})", RegionInfo.RegionName), ThreadPriority.Normal, false, false); |
1144 | } | 1209 | } |
@@ -1169,222 +1234,296 @@ namespace OpenSim.Region.Framework.Scenes | |||
1169 | /// </summary> | 1234 | /// </summary> |
1170 | private void Heartbeat() | 1235 | private void Heartbeat() |
1171 | { | 1236 | { |
1172 | if (!Monitor.TryEnter(m_heartbeatLock)) | 1237 | // if (!Monitor.TryEnter(m_heartbeatLock)) |
1173 | { | 1238 | // { |
1174 | Watchdog.RemoveThread(); | 1239 | // Watchdog.RemoveThread(); |
1175 | return; | 1240 | // return; |
1176 | } | 1241 | // } |
1177 | 1242 | ||
1178 | try | 1243 | // try |
1179 | { | 1244 | // { |
1180 | m_eventManager.TriggerOnRegionStarted(this); | ||
1181 | 1245 | ||
1182 | // The first frame can take a very long time due to physics actors being added on startup. Therefore, | 1246 | m_eventManager.TriggerOnRegionStarted(this); |
1183 | // don't turn on the watchdog alarm for this thread until the second frame, in order to prevent false | ||
1184 | // alarms for scenes with many objects. | ||
1185 | Update(); | ||
1186 | Watchdog.GetCurrentThreadInfo().AlarmIfTimeout = true; | ||
1187 | 1247 | ||
1188 | while (!shuttingdown) | 1248 | // The first frame can take a very long time due to physics actors being added on startup. Therefore, |
1189 | Update(); | 1249 | // don't turn on the watchdog alarm for this thread until the second frame, in order to prevent false |
1250 | // alarms for scenes with many objects. | ||
1251 | Update(1); | ||
1190 | 1252 | ||
1191 | m_lastUpdate = Util.EnvironmentTickCount(); | 1253 | Watchdog.StartThread( |
1192 | m_firstHeartbeat = false; | 1254 | Maintenance, string.Format("Maintenance ({0})", RegionInfo.RegionName), ThreadPriority.Normal, false, true); |
1193 | } | 1255 | |
1194 | catch (ThreadAbortException) | 1256 | Watchdog.GetCurrentThreadInfo().AlarmIfTimeout = true; |
1195 | { | 1257 | Update(-1); |
1196 | } | 1258 | |
1197 | finally | 1259 | // m_lastUpdate = Util.EnvironmentTickCount(); |
1198 | { | 1260 | // m_firstHeartbeat = false; |
1199 | Monitor.Pulse(m_heartbeatLock); | 1261 | // } |
1200 | Monitor.Exit(m_heartbeatLock); | 1262 | // finally |
1201 | } | 1263 | // { |
1264 | // Monitor.Pulse(m_heartbeatLock); | ||
1265 | // Monitor.Exit(m_heartbeatLock); | ||
1266 | // } | ||
1202 | 1267 | ||
1203 | Watchdog.RemoveThread(); | 1268 | Watchdog.RemoveThread(); |
1204 | } | 1269 | } |
1205 | 1270 | ||
1206 | public override void Update() | 1271 | private void Maintenance() |
1207 | { | 1272 | { |
1208 | float physicsFPS = 0f; | 1273 | DoMaintenance(-1); |
1209 | |||
1210 | int maintc = Util.EnvironmentTickCount(); | ||
1211 | int tmpFrameMS = maintc; | ||
1212 | agentMS = tempOnRezMS = eventMS = backupMS = terrainMS = landMS = 0; | ||
1213 | |||
1214 | ++Frame; | ||
1215 | |||
1216 | // m_log.DebugFormat("[SCENE]: Processing frame {0} in {1}", Frame, RegionInfo.RegionName); | ||
1217 | 1274 | ||
1218 | try | 1275 | Watchdog.RemoveThread(); |
1219 | { | 1276 | } |
1220 | int tmpPhysicsMS2 = Util.EnvironmentTickCount(); | ||
1221 | if ((Frame % m_update_physics == 0) && m_physics_enabled) | ||
1222 | m_sceneGraph.UpdatePreparePhysics(); | ||
1223 | physicsMS2 = Util.EnvironmentTickCountSubtract(tmpPhysicsMS2); | ||
1224 | |||
1225 | // Apply any pending avatar force input to the avatar's velocity | ||
1226 | int tmpAgentMS = Util.EnvironmentTickCount(); | ||
1227 | if (Frame % m_update_entitymovement == 0) | ||
1228 | m_sceneGraph.UpdateScenePresenceMovement(); | ||
1229 | agentMS = Util.EnvironmentTickCountSubtract(tmpAgentMS); | ||
1230 | |||
1231 | // Perform the main physics update. This will do the actual work of moving objects and avatars according to their | ||
1232 | // velocity | ||
1233 | int tmpPhysicsMS = Util.EnvironmentTickCount(); | ||
1234 | if (Frame % m_update_physics == 0) | ||
1235 | { | ||
1236 | if (m_physics_enabled) | ||
1237 | physicsFPS = m_sceneGraph.UpdatePhysics(MinFrameTime); | ||
1238 | |||
1239 | if (SynchronizeScene != null) | ||
1240 | SynchronizeScene(this); | ||
1241 | } | ||
1242 | physicsMS = Util.EnvironmentTickCountSubtract(tmpPhysicsMS); | ||
1243 | 1277 | ||
1244 | tmpAgentMS = Util.EnvironmentTickCount(); | 1278 | public void DoMaintenance(int runs) |
1279 | { | ||
1280 | long? endRun = null; | ||
1281 | int runtc; | ||
1282 | int previousMaintenanceTick; | ||
1245 | 1283 | ||
1246 | // Check if any objects have reached their targets | 1284 | if (runs >= 0) |
1247 | CheckAtTargets(); | 1285 | endRun = MaintenanceRun + runs; |
1248 | 1286 | ||
1249 | // Update SceneObjectGroups that have scheduled themselves for updates | 1287 | List<Vector3> coarseLocations; |
1250 | // Objects queue their updates onto all scene presences | 1288 | List<UUID> avatarUUIDs; |
1251 | if (Frame % m_update_objects == 0) | ||
1252 | m_sceneGraph.UpdateObjectGroups(); | ||
1253 | 1289 | ||
1254 | // Run through all ScenePresences looking for updates | 1290 | while (!m_shuttingDown && (endRun == null || MaintenanceRun < endRun)) |
1255 | // Presence updates and queued object updates for each presence are sent to clients | 1291 | { |
1256 | if (Frame % m_update_presences == 0) | 1292 | runtc = Util.EnvironmentTickCount(); |
1257 | m_sceneGraph.UpdatePresences(); | 1293 | ++MaintenanceRun; |
1258 | 1294 | ||
1259 | // Coarse locations relate to positions of green dots on the mini-map (on a SecondLife client) | 1295 | // Coarse locations relate to positions of green dots on the mini-map (on a SecondLife client) |
1260 | if (Frame % m_update_coarse_locations == 0) | 1296 | if (MaintenanceRun % (m_update_coarse_locations / 10) == 0) |
1261 | { | 1297 | { |
1262 | List<Vector3> coarseLocations; | ||
1263 | List<UUID> avatarUUIDs; | ||
1264 | SceneGraph.GetCoarseLocations(out coarseLocations, out avatarUUIDs, 60); | 1298 | SceneGraph.GetCoarseLocations(out coarseLocations, out avatarUUIDs, 60); |
1265 | // Send coarse locations to clients | 1299 | // Send coarse locations to clients |
1266 | ForEachScenePresence(delegate(ScenePresence presence) | 1300 | ForEachScenePresence(delegate(ScenePresence presence) |
1267 | { | 1301 | { |
1268 | presence.SendCoarseLocations(coarseLocations, avatarUUIDs); | 1302 | presence.SendCoarseLocations(coarseLocations, avatarUUIDs); |
1269 | }); | 1303 | }); |
1270 | } | 1304 | } |
1271 | 1305 | ||
1272 | agentMS += Util.EnvironmentTickCountSubtract(tmpAgentMS); | 1306 | if (SendPeriodicAppearanceUpdates && MaintenanceRun % 60 == 0) |
1273 | |||
1274 | // Delete temp-on-rez stuff | ||
1275 | if (Frame % m_update_temp_cleaning == 0 && !m_cleaningTemps) | ||
1276 | { | 1307 | { |
1277 | int tmpTempOnRezMS = Util.EnvironmentTickCount(); | 1308 | // m_log.DebugFormat("[SCENE]: Sending periodic appearance updates"); |
1278 | m_cleaningTemps = true; | ||
1279 | Util.FireAndForget(delegate { CleanTempObjects(); m_cleaningTemps = false; }); | ||
1280 | tempOnRezMS = Util.EnvironmentTickCountSubtract(tmpTempOnRezMS); | ||
1281 | } | ||
1282 | 1309 | ||
1283 | if (Frame % m_update_events == 0) | 1310 | if (AvatarFactory != null) |
1284 | { | 1311 | { |
1285 | int evMS = Util.EnvironmentTickCount(); | 1312 | ForEachRootScenePresence(sp => AvatarFactory.SendAppearance(sp.UUID)); |
1286 | UpdateEvents(); | 1313 | } |
1287 | eventMS = Util.EnvironmentTickCountSubtract(evMS); ; | ||
1288 | } | 1314 | } |
1289 | 1315 | ||
1290 | if (Frame % m_update_backup == 0) | 1316 | Watchdog.UpdateThread(); |
1291 | { | ||
1292 | int backMS = Util.EnvironmentTickCount(); | ||
1293 | UpdateStorageBackup(); | ||
1294 | backupMS = Util.EnvironmentTickCountSubtract(backMS); | ||
1295 | } | ||
1296 | 1317 | ||
1297 | if (Frame % m_update_terrain == 0) | 1318 | previousMaintenanceTick = m_lastMaintenanceTick; |
1298 | { | 1319 | m_lastMaintenanceTick = Util.EnvironmentTickCount(); |
1299 | int terMS = Util.EnvironmentTickCount(); | 1320 | runtc = Util.EnvironmentTickCountSubtract(m_lastMaintenanceTick, runtc); |
1300 | UpdateTerrain(); | 1321 | runtc = (int)(MinMaintenanceTime * 1000) - runtc; |
1301 | terrainMS = Util.EnvironmentTickCountSubtract(terMS); | 1322 | |
1302 | } | 1323 | if (runtc > 0) |
1324 | Thread.Sleep(runtc); | ||
1325 | |||
1326 | // Optionally warn if a frame takes double the amount of time that it should. | ||
1327 | if (DebugUpdates | ||
1328 | && Util.EnvironmentTickCountSubtract( | ||
1329 | m_lastMaintenanceTick, previousMaintenanceTick) > (int)(MinMaintenanceTime * 1000 * 2)) | ||
1330 | m_log.WarnFormat( | ||
1331 | "[SCENE]: Maintenance took {0} ms (desired max {1} ms) in {2}", | ||
1332 | Util.EnvironmentTickCountSubtract(m_lastMaintenanceTick, previousMaintenanceTick), | ||
1333 | MinMaintenanceTime * 1000, | ||
1334 | RegionInfo.RegionName); | ||
1335 | } | ||
1336 | } | ||
1337 | |||
1338 | public override void Update(int frames) | ||
1339 | { | ||
1340 | long? endFrame = null; | ||
1341 | |||
1342 | if (frames >= 0) | ||
1343 | endFrame = Frame + frames; | ||
1303 | 1344 | ||
1304 | //if (Frame % m_update_land == 0) | 1345 | float physicsFPS = 0f; |
1305 | //{ | 1346 | int tmpPhysicsMS, tmpPhysicsMS2, tmpAgentMS, tmpTempOnRezMS, evMS, backMS, terMS; |
1306 | // int ldMS = Util.EnvironmentTickCount(); | 1347 | int previousFrameTick; |
1307 | // UpdateLand(); | 1348 | int maintc; |
1308 | // landMS = Util.EnvironmentTickCountSubtract(ldMS); | 1349 | |
1309 | //} | 1350 | while (!m_shuttingDown && (endFrame == null || Frame < endFrame)) |
1310 | 1351 | { | |
1311 | frameMS = Util.EnvironmentTickCountSubtract(tmpFrameMS); | 1352 | maintc = Util.EnvironmentTickCount(); |
1312 | otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS; | 1353 | ++Frame; |
1313 | lastCompletedFrame = Util.EnvironmentTickCount(); | 1354 | |
1314 | 1355 | // m_log.DebugFormat("[SCENE]: Processing frame {0} in {1}", Frame, RegionInfo.RegionName); | |
1315 | // if (Frame%m_update_avatars == 0) | 1356 | |
1316 | // UpdateInWorldTime(); | 1357 | agentMS = tempOnRezMS = eventMS = backupMS = terrainMS = landMS = 0; |
1317 | StatsReporter.AddPhysicsFPS(physicsFPS); | 1358 | |
1318 | StatsReporter.AddTimeDilation(TimeDilation); | 1359 | try |
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.addAgentMS(agentMS); | ||
1326 | StatsReporter.addPhysicsMS(physicsMS + physicsMS2); | ||
1327 | StatsReporter.addOtherMS(otherMS); | ||
1328 | StatsReporter.SetActiveScripts(m_sceneGraph.GetActiveScriptsCount()); | ||
1329 | StatsReporter.addScriptLines(m_sceneGraph.GetScriptLPS()); | ||
1330 | |||
1331 | if (LoginsDisabled && Frame == 20) | ||
1332 | { | 1360 | { |
1333 | // m_log.DebugFormat("{0} {1} {2}", LoginsDisabled, m_sceneGraph.GetActiveScriptsCount(), LoginLock); | 1361 | tmpPhysicsMS2 = Util.EnvironmentTickCount(); |
1362 | if ((Frame % m_update_physics == 0) && m_physics_enabled) | ||
1363 | m_sceneGraph.UpdatePreparePhysics(); | ||
1364 | physicsMS2 = Util.EnvironmentTickCountSubtract(tmpPhysicsMS2); | ||
1365 | |||
1366 | // Apply any pending avatar force input to the avatar's velocity | ||
1367 | tmpAgentMS = Util.EnvironmentTickCount(); | ||
1368 | if (Frame % m_update_entitymovement == 0) | ||
1369 | m_sceneGraph.UpdateScenePresenceMovement(); | ||
1370 | agentMS = Util.EnvironmentTickCountSubtract(tmpAgentMS); | ||
1371 | |||
1372 | // Perform the main physics update. This will do the actual work of moving objects and avatars according to their | ||
1373 | // velocity | ||
1374 | tmpPhysicsMS = Util.EnvironmentTickCount(); | ||
1375 | if (Frame % m_update_physics == 0) | ||
1376 | { | ||
1377 | if (m_physics_enabled) | ||
1378 | physicsFPS = m_sceneGraph.UpdatePhysics(MinFrameTime); | ||
1379 | |||
1380 | if (SynchronizeScene != null) | ||
1381 | SynchronizeScene(this); | ||
1382 | } | ||
1383 | physicsMS = Util.EnvironmentTickCountSubtract(tmpPhysicsMS); | ||
1334 | 1384 | ||
1335 | // In 99.9% of cases it is a bad idea to manually force garbage collection. However, | 1385 | tmpAgentMS = Util.EnvironmentTickCount(); |
1336 | // this is a rare case where we know we have just went through a long cycle of heap | 1386 | |
1337 | // allocations, and there is no more work to be done until someone logs in | 1387 | // Check if any objects have reached their targets |
1338 | GC.Collect(); | 1388 | CheckAtTargets(); |
1389 | |||
1390 | // Update SceneObjectGroups that have scheduled themselves for updates | ||
1391 | // Objects queue their updates onto all scene presences | ||
1392 | if (Frame % m_update_objects == 0) | ||
1393 | m_sceneGraph.UpdateObjectGroups(); | ||
1394 | |||
1395 | // Run through all ScenePresences looking for updates | ||
1396 | // Presence updates and queued object updates for each presence are sent to clients | ||
1397 | if (Frame % m_update_presences == 0) | ||
1398 | m_sceneGraph.UpdatePresences(); | ||
1399 | |||
1400 | agentMS += Util.EnvironmentTickCountSubtract(tmpAgentMS); | ||
1401 | |||
1402 | // Delete temp-on-rez stuff | ||
1403 | if (Frame % m_update_temp_cleaning == 0 && !m_cleaningTemps) | ||
1404 | { | ||
1405 | tmpTempOnRezMS = Util.EnvironmentTickCount(); | ||
1406 | m_cleaningTemps = true; | ||
1407 | Util.FireAndForget(delegate { CleanTempObjects(); m_cleaningTemps = false; }); | ||
1408 | tempOnRezMS = Util.EnvironmentTickCountSubtract(tmpTempOnRezMS); | ||
1409 | } | ||
1410 | |||
1411 | if (Frame % m_update_events == 0) | ||
1412 | { | ||
1413 | evMS = Util.EnvironmentTickCount(); | ||
1414 | UpdateEvents(); | ||
1415 | eventMS = Util.EnvironmentTickCountSubtract(evMS); | ||
1416 | } | ||
1417 | |||
1418 | if (Frame % m_update_backup == 0) | ||
1419 | { | ||
1420 | backMS = Util.EnvironmentTickCount(); | ||
1421 | UpdateStorageBackup(); | ||
1422 | backupMS = Util.EnvironmentTickCountSubtract(backMS); | ||
1423 | } | ||
1424 | |||
1425 | if (Frame % m_update_terrain == 0) | ||
1426 | { | ||
1427 | terMS = Util.EnvironmentTickCount(); | ||
1428 | UpdateTerrain(); | ||
1429 | terrainMS = Util.EnvironmentTickCountSubtract(terMS); | ||
1430 | } | ||
1431 | |||
1432 | //if (Frame % m_update_land == 0) | ||
1433 | //{ | ||
1434 | // int ldMS = Util.EnvironmentTickCount(); | ||
1435 | // UpdateLand(); | ||
1436 | // landMS = Util.EnvironmentTickCountSubtract(ldMS); | ||
1437 | //} | ||
1339 | 1438 | ||
1340 | IConfig startupConfig = m_config.Configs["Startup"]; | 1439 | frameMS = Util.EnvironmentTickCountSubtract(maintc); |
1341 | if (startupConfig == null || !startupConfig.GetBoolean("StartDisabled", false)) | 1440 | otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS; |
1441 | |||
1442 | // if (Frame%m_update_avatars == 0) | ||
1443 | // UpdateInWorldTime(); | ||
1444 | StatsReporter.AddPhysicsFPS(physicsFPS); | ||
1445 | StatsReporter.AddTimeDilation(TimeDilation); | ||
1446 | StatsReporter.AddFPS(1); | ||
1447 | StatsReporter.SetRootAgents(m_sceneGraph.GetRootAgentCount()); | ||
1448 | StatsReporter.SetChildAgents(m_sceneGraph.GetChildAgentCount()); | ||
1449 | StatsReporter.SetObjects(m_sceneGraph.GetTotalObjectsCount()); | ||
1450 | StatsReporter.SetActiveObjects(m_sceneGraph.GetActiveObjectsCount()); | ||
1451 | |||
1452 | // frameMS currently records work frame times, not total frame times (work + any required sleep to | ||
1453 | // reach min frame time. | ||
1454 | StatsReporter.addFrameMS(frameMS); | ||
1455 | |||
1456 | StatsReporter.addAgentMS(agentMS); | ||
1457 | StatsReporter.addPhysicsMS(physicsMS + physicsMS2); | ||
1458 | StatsReporter.addOtherMS(otherMS); | ||
1459 | StatsReporter.SetActiveScripts(m_sceneGraph.GetActiveScriptsCount()); | ||
1460 | StatsReporter.addScriptLines(m_sceneGraph.GetScriptLPS()); | ||
1461 | |||
1462 | if (LoginsDisabled && Frame == 20) | ||
1342 | { | 1463 | { |
1343 | // This handles a case of a region having no scripts for the RegionReady module | 1464 | // m_log.DebugFormat("{0} {1} {2}", LoginsDisabled, m_sceneGraph.GetActiveScriptsCount(), LoginLock); |
1344 | if (m_sceneGraph.GetActiveScriptsCount() == 0) | 1465 | |
1466 | // In 99.9% of cases it is a bad idea to manually force garbage collection. However, | ||
1467 | // this is a rare case where we know we have just went through a long cycle of heap | ||
1468 | // allocations, and there is no more work to be done until someone logs in | ||
1469 | GC.Collect(); | ||
1470 | |||
1471 | IConfig startupConfig = m_config.Configs["Startup"]; | ||
1472 | if (startupConfig == null || !startupConfig.GetBoolean("StartDisabled", false)) | ||
1345 | { | 1473 | { |
1346 | // need to be able to tell these have changed in RegionReady | 1474 | // This handles a case of a region having no scripts for the RegionReady module |
1347 | LoginLock = false; | 1475 | if (m_sceneGraph.GetActiveScriptsCount() == 0) |
1348 | EventManager.TriggerLoginsEnabled(RegionInfo.RegionName); | 1476 | { |
1477 | // need to be able to tell these have changed in RegionReady | ||
1478 | LoginLock = false; | ||
1479 | EventManager.TriggerLoginsEnabled(RegionInfo.RegionName); | ||
1480 | } | ||
1481 | m_log.DebugFormat("[REGION]: Enabling logins for {0}", RegionInfo.RegionName); | ||
1482 | |||
1483 | // For RegionReady lockouts | ||
1484 | if(LoginLock == false) | ||
1485 | { | ||
1486 | LoginsDisabled = false; | ||
1487 | } | ||
1488 | |||
1489 | m_sceneGridService.InformNeighborsThatRegionisUp(RequestModuleInterface<INeighbourService>(), RegionInfo); | ||
1349 | } | 1490 | } |
1350 | m_log.DebugFormat("[REGION]: Enabling logins for {0}", RegionInfo.RegionName); | 1491 | else |
1351 | |||
1352 | // For RegionReady lockouts | ||
1353 | if(LoginLock == false) | ||
1354 | { | 1492 | { |
1355 | LoginsDisabled = false; | 1493 | StartDisabled = true; |
1494 | LoginsDisabled = true; | ||
1356 | } | 1495 | } |
1357 | |||
1358 | m_sceneGridService.InformNeighborsThatRegionisUp(RequestModuleInterface<INeighbourService>(), RegionInfo); | ||
1359 | } | ||
1360 | else | ||
1361 | { | ||
1362 | StartDisabled = true; | ||
1363 | LoginsDisabled = true; | ||
1364 | } | 1496 | } |
1365 | } | 1497 | } |
1366 | } | 1498 | catch (Exception e) |
1367 | catch (NotImplementedException) | 1499 | { |
1368 | { | 1500 | m_log.ErrorFormat( |
1369 | throw; | 1501 | "[SCENE]: Failed on region {0} with exception {1}{2}", |
1370 | } | 1502 | RegionInfo.RegionName, e.Message, e.StackTrace); |
1371 | catch (Exception e) | 1503 | } |
1372 | { | 1504 | |
1373 | m_log.ErrorFormat( | 1505 | EventManager.TriggerRegionHeartbeatEnd(this); |
1374 | "[SCENE]: Failed on region {0} with exception {1}{2}", | ||
1375 | RegionInfo.RegionName, e.Message, e.StackTrace); | ||
1376 | } | ||
1377 | 1506 | ||
1378 | EventManager.TriggerRegionHeartbeatEnd(this); | 1507 | Watchdog.UpdateThread(); |
1379 | 1508 | ||
1380 | maintc = Util.EnvironmentTickCountSubtract(maintc); | 1509 | previousFrameTick = m_lastFrameTick; |
1381 | maintc = (int)(MinFrameTime * 1000) - maintc; | 1510 | m_lastFrameTick = Util.EnvironmentTickCount(); |
1511 | maintc = Util.EnvironmentTickCountSubtract(m_lastFrameTick, maintc); | ||
1512 | maintc = (int)(MinFrameTime * 1000) - maintc; | ||
1382 | 1513 | ||
1383 | if (maintc > 0) | 1514 | if (maintc > 0) |
1384 | Thread.Sleep(maintc); | 1515 | Thread.Sleep(maintc); |
1385 | 1516 | ||
1386 | // Tell the watchdog that this thread is still alive | 1517 | // Optionally warn if a frame takes double the amount of time that it should. |
1387 | Watchdog.UpdateThread(); | 1518 | if (DebugUpdates |
1519 | && Util.EnvironmentTickCountSubtract( | ||
1520 | m_lastFrameTick, previousFrameTick) > (int)(MinFrameTime * 1000 * 2)) | ||
1521 | m_log.WarnFormat( | ||
1522 | "[SCENE]: Frame took {0} ms (desired max {1} ms) in {2}", | ||
1523 | Util.EnvironmentTickCountSubtract(m_lastFrameTick, previousFrameTick), | ||
1524 | MinFrameTime * 1000, | ||
1525 | RegionInfo.RegionName); | ||
1526 | } | ||
1388 | } | 1527 | } |
1389 | 1528 | ||
1390 | public void AddGroupTarget(SceneObjectGroup grp) | 1529 | public void AddGroupTarget(SceneObjectGroup grp) |
@@ -1583,8 +1722,15 @@ namespace OpenSim.Region.Framework.Scenes | |||
1583 | double[,] map = SimulationDataService.LoadTerrain(RegionInfo.RegionID); | 1722 | double[,] map = SimulationDataService.LoadTerrain(RegionInfo.RegionID); |
1584 | if (map == null) | 1723 | if (map == null) |
1585 | { | 1724 | { |
1586 | m_log.Info("[TERRAIN]: No default terrain. Generating a new terrain."); | 1725 | // This should be in the Terrain module, but it isn't because |
1587 | Heightmap = new TerrainChannel(); | 1726 | // the heightmap is needed _way_ before the modules are initialized... |
1727 | IConfig terrainConfig = m_config.Configs["Terrain"]; | ||
1728 | String m_InitialTerrain = "pinhead-island"; | ||
1729 | if (terrainConfig != null) | ||
1730 | m_InitialTerrain = terrainConfig.GetString("InitialTerrain", m_InitialTerrain); | ||
1731 | |||
1732 | m_log.InfoFormat("[TERRAIN]: No default terrain. Generating a new terrain {0}.", m_InitialTerrain); | ||
1733 | Heightmap = new TerrainChannel(m_InitialTerrain); | ||
1588 | 1734 | ||
1589 | SimulationDataService.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID); | 1735 | SimulationDataService.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID); |
1590 | } | 1736 | } |
@@ -1999,15 +2145,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
1999 | public void DeleteSceneObject(SceneObjectGroup group, bool silent) | 2145 | public void DeleteSceneObject(SceneObjectGroup group, bool silent) |
2000 | { | 2146 | { |
2001 | // m_log.DebugFormat("[SCENE]: Deleting scene object {0} {1}", group.Name, group.UUID); | 2147 | // m_log.DebugFormat("[SCENE]: Deleting scene object {0} {1}", group.Name, group.UUID); |
2002 | |||
2003 | //SceneObjectPart rootPart = group.GetChildPart(group.UUID); | ||
2004 | 2148 | ||
2005 | // Serialise calls to RemoveScriptInstances to avoid | 2149 | group.RemoveScriptInstances(true); |
2006 | // deadlocking on m_parts inside SceneObjectGroup | ||
2007 | lock (m_deleting_scene_object) | ||
2008 | { | ||
2009 | group.RemoveScriptInstances(true); | ||
2010 | } | ||
2011 | 2150 | ||
2012 | SceneObjectPart[] partList = group.Parts; | 2151 | SceneObjectPart[] partList = group.Parts; |
2013 | 2152 | ||
@@ -2489,7 +2628,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2489 | = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0 | 2628 | = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0 |
2490 | || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; | 2629 | || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; |
2491 | 2630 | ||
2492 | CheckHeartbeat(); | 2631 | // CheckHeartbeat(); |
2493 | 2632 | ||
2494 | ScenePresence sp = GetScenePresence(client.AgentId); | 2633 | ScenePresence sp = GetScenePresence(client.AgentId); |
2495 | 2634 | ||
@@ -2536,6 +2675,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
2536 | // Cache the user's name | 2675 | // Cache the user's name |
2537 | CacheUserName(sp, aCircuit); | 2676 | CacheUserName(sp, aCircuit); |
2538 | 2677 | ||
2678 | // Let's send the Suitcase folder for incoming HG agents | ||
2679 | if ((aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0) | ||
2680 | { | ||
2681 | m_log.DebugFormat("[SCENE]: Sending root folder to viewer..."); | ||
2682 | InventoryFolderBase suitcase = InventoryService.GetRootFolder(client.AgentId); | ||
2683 | client.SendBulkUpdateInventory(suitcase); | ||
2684 | } | ||
2685 | |||
2539 | EventManager.TriggerOnNewClient(client); | 2686 | EventManager.TriggerOnNewClient(client); |
2540 | if (vialogin) | 2687 | if (vialogin) |
2541 | EventManager.TriggerOnClientLogin(client); | 2688 | EventManager.TriggerOnClientLogin(client); |
@@ -2774,7 +2921,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
2774 | { | 2921 | { |
2775 | //client.OnNameFromUUIDRequest += HandleUUIDNameRequest; | 2922 | //client.OnNameFromUUIDRequest += HandleUUIDNameRequest; |
2776 | client.OnMoneyTransferRequest += ProcessMoneyTransferRequest; | 2923 | client.OnMoneyTransferRequest += ProcessMoneyTransferRequest; |
2777 | client.OnAvatarPickerRequest += ProcessAvatarPickerRequest; | ||
2778 | client.OnSetStartLocationRequest += SetHomeRezPoint; | 2924 | client.OnSetStartLocationRequest += SetHomeRezPoint; |
2779 | client.OnRegionHandleRequest += RegionHandleRequest; | 2925 | client.OnRegionHandleRequest += RegionHandleRequest; |
2780 | } | 2926 | } |
@@ -2900,7 +3046,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
2900 | { | 3046 | { |
2901 | //client.OnNameFromUUIDRequest -= HandleUUIDNameRequest; | 3047 | //client.OnNameFromUUIDRequest -= HandleUUIDNameRequest; |
2902 | client.OnMoneyTransferRequest -= ProcessMoneyTransferRequest; | 3048 | client.OnMoneyTransferRequest -= ProcessMoneyTransferRequest; |
2903 | client.OnAvatarPickerRequest -= ProcessAvatarPickerRequest; | ||
2904 | client.OnSetStartLocationRequest -= SetHomeRezPoint; | 3049 | client.OnSetStartLocationRequest -= SetHomeRezPoint; |
2905 | client.OnRegionHandleRequest -= RegionHandleRequest; | 3050 | client.OnRegionHandleRequest -= RegionHandleRequest; |
2906 | } | 3051 | } |
@@ -3067,7 +3212,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3067 | 3212 | ||
3068 | public override void RemoveClient(UUID agentID, bool closeChildAgents) | 3213 | public override void RemoveClient(UUID agentID, bool closeChildAgents) |
3069 | { | 3214 | { |
3070 | CheckHeartbeat(); | 3215 | // CheckHeartbeat(); |
3071 | bool isChildAgent = false; | 3216 | bool isChildAgent = false; |
3072 | ScenePresence avatar = GetScenePresence(agentID); | 3217 | ScenePresence avatar = GetScenePresence(agentID); |
3073 | if (avatar != null) | 3218 | if (avatar != null) |
@@ -3540,8 +3685,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
3540 | if (!AuthorizationService.IsAuthorizedForRegion( | 3685 | if (!AuthorizationService.IsAuthorizedForRegion( |
3541 | agent.AgentID.ToString(), agent.firstname, agent.lastname, RegionInfo.RegionID.ToString(), out reason)) | 3686 | agent.AgentID.ToString(), agent.firstname, agent.lastname, RegionInfo.RegionID.ToString(), out reason)) |
3542 | { | 3687 | { |
3543 | m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the region", | 3688 | m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because {4}", |
3544 | agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); | 3689 | agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName, reason); |
3545 | 3690 | ||
3546 | return false; | 3691 | return false; |
3547 | } | 3692 | } |
@@ -4156,16 +4301,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
4156 | public bool PipeEventsForScript(uint localID) | 4301 | public bool PipeEventsForScript(uint localID) |
4157 | { | 4302 | { |
4158 | SceneObjectPart part = GetSceneObjectPart(localID); | 4303 | SceneObjectPart part = GetSceneObjectPart(localID); |
4304 | |||
4159 | if (part != null) | 4305 | if (part != null) |
4160 | { | 4306 | { |
4161 | // Changed so that child prims of attachments return ScriptDanger for their parent, so that | ||
4162 | // their scripts will actually run. | ||
4163 | // -- Leaf, Tue Aug 12 14:17:05 EDT 2008 | ||
4164 | SceneObjectPart parent = part.ParentGroup.RootPart; | 4307 | SceneObjectPart parent = part.ParentGroup.RootPart; |
4165 | if (part.ParentGroup.IsAttachment) | 4308 | return ScriptDanger(parent, parent.GetWorldPosition()); |
4166 | return ScriptDanger(parent, parent.GetWorldPosition()); | ||
4167 | else | ||
4168 | return ScriptDanger(part, part.GetWorldPosition()); | ||
4169 | } | 4309 | } |
4170 | else | 4310 | else |
4171 | { | 4311 | { |
@@ -4459,8 +4599,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
4459 | // | 4599 | // |
4460 | int health=1; // Start at 1, means we're up | 4600 | int health=1; // Start at 1, means we're up |
4461 | 4601 | ||
4462 | if ((Util.EnvironmentTickCountSubtract(m_lastUpdate)) < 1000) | 4602 | if ((Util.EnvironmentTickCountSubtract(m_lastFrameTick)) < 1000) |
4463 | health+=1; | 4603 | health += 1; |
4464 | else | 4604 | else |
4465 | return health; | 4605 | return health; |
4466 | 4606 | ||
@@ -4471,7 +4611,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
4471 | else | 4611 | else |
4472 | return health; | 4612 | return health; |
4473 | 4613 | ||
4474 | CheckHeartbeat(); | 4614 | // CheckHeartbeat(); |
4475 | 4615 | ||
4476 | return health; | 4616 | return health; |
4477 | } | 4617 | } |
@@ -4659,14 +4799,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
4659 | return (((vsn.X * xdiff) + (vsn.Y * ydiff)) / (-1 * vsn.Z)) + p0.Z; | 4799 | return (((vsn.X * xdiff) + (vsn.Y * ydiff)) / (-1 * vsn.Z)) + p0.Z; |
4660 | } | 4800 | } |
4661 | 4801 | ||
4662 | private void CheckHeartbeat() | 4802 | // private void CheckHeartbeat() |
4663 | { | 4803 | // { |
4664 | if (m_firstHeartbeat) | 4804 | // if (m_firstHeartbeat) |
4665 | return; | 4805 | // return; |
4666 | 4806 | // | |
4667 | if (Util.EnvironmentTickCountSubtract(m_lastUpdate) > 2000) | 4807 | // if (Util.EnvironmentTickCountSubtract(m_lastFrameTick) > 2000) |
4668 | StartTimer(); | 4808 | // StartTimer(); |
4669 | } | 4809 | // } |
4670 | 4810 | ||
4671 | public override ISceneObject DeserializeObject(string representation) | 4811 | public override ISceneObject DeserializeObject(string representation) |
4672 | { | 4812 | { |