From 31304c222df1e5a832afd0ebcf7d3ed403543e54 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 25 Jul 2012 21:00:59 +0100 Subject: Make SceneManager.OnRegionsReadyStatusChange event available. This is fired when all regions are ready or when at least one region becomes not ready. Recently added EventManager.OnRegionReady becomes OnRegionReadyStatusChange to match OnLoginsEnabledStatusChange --- OpenSim/Framework/IScene.cs | 8 ++++ .../MapImage/MapImageServiceModule.cs | 7 +-- OpenSim/Region/Framework/Scenes/EventManager.cs | 11 ++--- OpenSim/Region/Framework/Scenes/Scene.cs | 4 +- OpenSim/Region/Framework/Scenes/SceneBase.cs | 18 ++++++++ OpenSim/Region/Framework/Scenes/SceneManager.cs | 53 +++++++++++++++++++++- .../RegionReadyModule/RegionReadyModule.cs | 2 +- OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | 2 +- 8 files changed, 87 insertions(+), 18 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Framework/IScene.cs b/OpenSim/Framework/IScene.cs index 2c38e0f..87ec99e 100644 --- a/OpenSim/Framework/IScene.cs +++ b/OpenSim/Framework/IScene.cs @@ -71,6 +71,14 @@ namespace OpenSim.Framework /// bool LoginsEnabled { get; set; } + /// + /// Is this region ready for use? + /// + /// + /// This does not mean that logins are enabled, merely that they can be. + /// + bool Ready { get; set; } + float TimeDilation { get; } bool AllowScriptCrossings { get; } diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs index 5641804..9d282b8 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs @@ -131,11 +131,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage /// /// /// - - - /// - /// - /// public void AddRegion(Scene scene) { if (! m_enabled) @@ -146,7 +141,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage lock (m_scenes) m_scenes[scene.RegionInfo.RegionID] = scene; - scene.EventManager.OnRegionReady += s => UploadMapTile(s); + scene.EventManager.OnRegionReadyStatusChange += s => { if (s.Ready) UploadMapTile(s); }; } /// diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index 620b605..6dea2f0 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -513,8 +513,7 @@ namespace OpenSim.Region.Framework.Scenes /// A region is considered ready when startup operations such as loading of scripts already on the region /// have been completed. /// - public event RegionReady OnRegionReady; - public delegate void RegionReady(IScene scene); + public event Action OnRegionReadyStatusChange; public delegate void PrimsLoaded(Scene s); public event PrimsLoaded OnPrimsLoaded; @@ -2508,13 +2507,13 @@ namespace OpenSim.Region.Framework.Scenes } } - public void TriggerRegionReady(IScene scene) + public void TriggerRegionReadyStatusChange(IScene scene) { - RegionReady handler = OnRegionReady; + Action handler = OnRegionReadyStatusChange; if (handler != null) { - foreach (RegionReady d in handler.GetInvocationList()) + foreach (Action d in handler.GetInvocationList()) { try { @@ -2522,7 +2521,7 @@ namespace OpenSim.Region.Framework.Scenes } catch (Exception e) { - m_log.ErrorFormat("[EVENT MANAGER]: Delegate for OnRegionReady failed - continuing {0} - {1}", + m_log.ErrorFormat("[EVENT MANAGER]: Delegate for OnRegionReadyStatusChange failed - continuing {0} - {1}", e.Message, e.StackTrace); } } diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index ee34338..20918bd 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1499,8 +1499,8 @@ namespace OpenSim.Region.Framework.Scenes m_sceneGridService.InformNeighborsThatRegionisUp( RequestModuleInterface(), RegionInfo); - // Region ready should always be triggered whether logins are immediately enabled or not. - EventManager.TriggerRegionReady(this); + // Region ready should always be set + Ready = true; } else { diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs index 282fc5e..b87a38a 100644 --- a/OpenSim/Region/Framework/Scenes/SceneBase.cs +++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs @@ -124,6 +124,24 @@ namespace OpenSim.Region.Framework.Scenes } private bool m_loginsEnabled; + public bool Ready + { + get + { + return m_ready; + } + + set + { + if (m_ready != value) + { + m_ready = value; + EventManager.TriggerRegionReadyStatusChange(this); + } + } + } + private bool m_ready; + public float TimeDilation { get { return 1.0f; } diff --git a/OpenSim/Region/Framework/Scenes/SceneManager.cs b/OpenSim/Region/Framework/Scenes/SceneManager.cs index d73a959..c81b55d 100644 --- a/OpenSim/Region/Framework/Scenes/SceneManager.cs +++ b/OpenSim/Region/Framework/Scenes/SceneManager.cs @@ -47,6 +47,48 @@ namespace OpenSim.Region.Framework.Scenes public event RestartSim OnRestartSim; + /// + /// Fired when either all regions are ready for use or at least one region has become unready for use where + /// previously all regions were ready. + /// + public event Action OnRegionsReadyStatusChange; + + /// + /// Are all regions ready for use? + /// + public bool AllRegionsReady + { + get + { + return m_allRegionsReady; + } + + private set + { + if (m_allRegionsReady != value) + { + m_allRegionsReady = value; + Action handler = OnRegionsReadyStatusChange; + if (handler != null) + { + foreach (Action d in handler.GetInvocationList()) + { + try + { + d(this); + } + catch (Exception e) + { + m_log.ErrorFormat("[SCENE MANAGER]: Delegate for OnRegionsReadyStatusChange failed - continuing {0} - {1}", + e.Message, e.StackTrace); + } + } + } + } + } + } + private bool m_allRegionsReady; + private static SceneManager m_instance = null; public static SceneManager Instance { @@ -141,10 +183,11 @@ namespace OpenSim.Region.Framework.Scenes public void Add(Scene scene) { - scene.OnRestart += HandleRestart; - lock (m_localScenes) m_localScenes.Add(scene); + + scene.OnRestart += HandleRestart; + scene.EventManager.OnRegionReadyStatusChange += HandleRegionReadyStatusChange; } public void HandleRestart(RegionInfo rdata) @@ -175,6 +218,12 @@ namespace OpenSim.Region.Framework.Scenes OnRestartSim(rdata); } + private void HandleRegionReadyStatusChange(IScene scene) + { + lock (m_localScenes) + AllRegionsReady = m_localScenes.TrueForAll(s => s.Ready); + } + public void SendSimOnlineNotification(ulong regionHandle) { RegionInfo Result = null; diff --git a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs index f459b8c..fff3a32 100644 --- a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs @@ -225,7 +225,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady RRAlert("enabled"); } - m_scene.EventManager.TriggerRegionReady(m_scene); + m_scene.Ready = true; } public void OarLoadingAlert(string msg) diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index da344d6..2dba029 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -646,7 +646,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine // If region ready has been triggered, then the region had no scripts to compile and completed its other // work. - m_Scene.EventManager.OnRegionReady += s => m_InitialStartup = false; + m_Scene.EventManager.OnRegionReadyStatusChange += s => { if (s.Ready) m_InitialStartup = false; }; if (m_SleepTime > 0) { -- cgit v1.1 From a1e99642c19810f98084e77723df1e242d2c26d0 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 25 Jul 2012 22:29:40 +0100 Subject: Add experimental "OpenSim object memory churn" statistics to output of region console "show stats" command This aims to capture the amount of memory that OpenSim turns over whilst operating a region. This memory is not lost - apart from leaks it is reclaimed by the garbage collector. However, the more memory that gets turned over the more work the GC has to do to reclaim it. --- OpenSim/Framework/Statistics/BaseStatsCollector.cs | 20 +++--- OpenSim/Framework/Watchdog.cs | 3 + OpenSim/Region/Application/OpenSim.cs | 72 +++++++++++----------- OpenSim/Region/Application/OpenSimBase.cs | 36 ++++++----- .../Region/ClientStack/RegionApplicationBase.cs | 4 +- 5 files changed, 72 insertions(+), 63 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Framework/Statistics/BaseStatsCollector.cs b/OpenSim/Framework/Statistics/BaseStatsCollector.cs index c9e57ce..28ce650 100644 --- a/OpenSim/Framework/Statistics/BaseStatsCollector.cs +++ b/OpenSim/Framework/Statistics/BaseStatsCollector.cs @@ -44,14 +44,18 @@ namespace OpenSim.Framework.Statistics StringBuilder sb = new StringBuilder(Environment.NewLine); sb.Append("MEMORY STATISTICS"); sb.Append(Environment.NewLine); - sb.Append( - string.Format( - "Allocated to OpenSim objects: {0} MB\n", - Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0))); - sb.Append( - string.Format( - "Process memory : {0} MB\n", - Math.Round(Process.GetCurrentProcess().WorkingSet64 / 1024.0 / 1024.0))); + + sb.AppendFormat( + "Allocated to OpenSim objects: {0} MB\n", + Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0)); + + sb.AppendFormat( + "OpenSim object memory churn : {0} KB/s\n", + Math.Round((MemoryWatchdog.AverageMemoryChurn * 1000) / 1024.0 / 1024, 3)); + + sb.AppendFormat( + "Process memory : {0} MB\n", + Math.Round(Process.GetCurrentProcess().WorkingSet64 / 1024.0 / 1024.0)); return sb.ToString(); } diff --git a/OpenSim/Framework/Watchdog.cs b/OpenSim/Framework/Watchdog.cs index 8a74f53..54e3d1a 100644 --- a/OpenSim/Framework/Watchdog.cs +++ b/OpenSim/Framework/Watchdog.cs @@ -325,6 +325,9 @@ namespace OpenSim.Framework callback(callbackInfo); } + if (MemoryWatchdog.Enabled) + MemoryWatchdog.Update(); + m_watchdogTimer.Start(); } } diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs index a4d85ac..f68974c 100644 --- a/OpenSim/Region/Application/OpenSim.cs +++ b/OpenSim/Region/Application/OpenSim.cs @@ -200,9 +200,9 @@ namespace OpenSim PrintFileToConsole("startuplogo.txt"); // For now, start at the 'root' level by default - if (m_sceneManager.Scenes.Count == 1) // If there is only one region, select it + if (SceneManager.Scenes.Count == 1) // If there is only one region, select it ChangeSelectedRegion("region", - new string[] {"change", "region", m_sceneManager.Scenes[0].RegionInfo.RegionName}); + new string[] {"change", "region", SceneManager.Scenes[0].RegionInfo.RegionName}); else ChangeSelectedRegion("region", new string[] {"change", "region", "root"}); @@ -461,7 +461,7 @@ namespace OpenSim if (cmdparams.Length > 4) alert = String.Format("\n{0}\n", String.Join(" ", cmdparams, 4, cmdparams.Length - 4)); - IList agents = m_sceneManager.GetCurrentSceneAvatars(); + IList agents = SceneManager.GetCurrentSceneAvatars(); foreach (ScenePresence presence in agents) { @@ -542,7 +542,7 @@ namespace OpenSim private void HandleForceUpdate(string module, string[] args) { MainConsole.Instance.Output("Updating all clients"); - m_sceneManager.ForceCurrentSceneClientUpdate(); + SceneManager.ForceCurrentSceneClientUpdate(); } /// @@ -554,7 +554,7 @@ namespace OpenSim { if (args.Length == 6) { - m_sceneManager.HandleEditCommandOnCurrentScene(args); + SceneManager.HandleEditCommandOnCurrentScene(args); } else { @@ -765,7 +765,7 @@ namespace OpenSim case "load": if (cmdparams.Length > 1) { - foreach (Scene s in new ArrayList(m_sceneManager.Scenes)) + foreach (Scene s in new ArrayList(SceneManager.Scenes)) { MainConsole.Instance.Output(String.Format("Loading module: {0}", cmdparams[1])); m_moduleLoader.LoadRegionModules(cmdparams[1], s); @@ -803,14 +803,14 @@ namespace OpenSim case "backup": MainConsole.Instance.Output("Triggering save of pending object updates to persistent store"); - m_sceneManager.BackupCurrentScene(); + SceneManager.BackupCurrentScene(); break; case "remove-region": string regRemoveName = CombineParams(cmdparams, 0); Scene removeScene; - if (m_sceneManager.TryGetScene(regRemoveName, out removeScene)) + if (SceneManager.TryGetScene(regRemoveName, out removeScene)) RemoveRegion(removeScene, false); else MainConsole.Instance.Output("No region with that name"); @@ -820,14 +820,14 @@ namespace OpenSim string regDeleteName = CombineParams(cmdparams, 0); Scene killScene; - if (m_sceneManager.TryGetScene(regDeleteName, out killScene)) + if (SceneManager.TryGetScene(regDeleteName, out killScene)) RemoveRegion(killScene, true); else MainConsole.Instance.Output("no region with that name"); break; case "restart": - m_sceneManager.RestartCurrentScene(); + SceneManager.RestartCurrentScene(); break; } } @@ -842,7 +842,7 @@ namespace OpenSim { string newRegionName = CombineParams(cmdparams, 2); - if (!m_sceneManager.TrySetCurrentScene(newRegionName)) + if (!SceneManager.TrySetCurrentScene(newRegionName)) MainConsole.Instance.Output(String.Format("Couldn't select region {0}", newRegionName)); } else @@ -850,7 +850,7 @@ namespace OpenSim MainConsole.Instance.Output("Usage: change region "); } - string regionName = (m_sceneManager.CurrentScene == null ? "root" : m_sceneManager.CurrentScene.RegionInfo.RegionName); + string regionName = (SceneManager.CurrentScene == null ? "root" : SceneManager.CurrentScene.RegionInfo.RegionName); MainConsole.Instance.Output(String.Format("Currently selected region is {0}", regionName)); // m_log.DebugFormat("Original prompt is {0}", m_consolePrompt); @@ -868,7 +868,7 @@ namespace OpenSim }); m_console.DefaultPrompt = prompt; - m_console.ConsoleScene = m_sceneManager.CurrentScene; + m_console.ConsoleScene = SceneManager.CurrentScene; } /// @@ -892,7 +892,7 @@ namespace OpenSim int newDebug; if (int.TryParse(args[2], out newDebug)) { - m_sceneManager.SetDebugPacketLevelOnCurrentScene(newDebug, name); + SceneManager.SetDebugPacketLevelOnCurrentScene(newDebug, name); // We provide user information elsewhere if any clients had their debug level set. // MainConsole.Instance.OutputFormat("Debug packet level set to {0}", newDebug); } @@ -907,7 +907,7 @@ namespace OpenSim case "scene": if (args.Length == 4) { - if (m_sceneManager.CurrentScene == null) + if (SceneManager.CurrentScene == null) { MainConsole.Instance.Output("Please use 'change region ' first"); } @@ -915,7 +915,7 @@ namespace OpenSim { string key = args[2]; string value = args[3]; - m_sceneManager.CurrentScene.SetSceneCoreDebug( + SceneManager.CurrentScene.SetSceneCoreDebug( new Dictionary() { { key, value } }); MainConsole.Instance.OutputFormat("Set debug scene {0} = {1}", key, value); @@ -954,10 +954,10 @@ namespace OpenSim IList agents; if (showParams.Length > 1 && showParams[1] == "full") { - agents = m_sceneManager.GetCurrentScenePresences(); + agents = SceneManager.GetCurrentScenePresences(); } else { - agents = m_sceneManager.GetCurrentSceneAvatars(); + agents = SceneManager.GetCurrentSceneAvatars(); } MainConsole.Instance.Output(String.Format("\nAgents connected: {0}\n", agents.Count)); @@ -1037,7 +1037,7 @@ namespace OpenSim MainConsole.Instance.Output("Shared Module: " + module.Name); } - m_sceneManager.ForEachScene( + SceneManager.ForEachScene( delegate(Scene scene) { m_log.Error("The currently loaded modules in " + scene.RegionInfo.RegionName + " are:"); foreach (IRegionModule module in scene.Modules.Values) @@ -1050,7 +1050,7 @@ namespace OpenSim } ); - m_sceneManager.ForEachScene( + SceneManager.ForEachScene( delegate(Scene scene) { MainConsole.Instance.Output("Loaded new region modules in" + scene.RegionInfo.RegionName + " are:"); foreach (IRegionModuleBase module in scene.RegionModules.Values) @@ -1066,7 +1066,7 @@ namespace OpenSim break; case "regions": - m_sceneManager.ForEachScene( + SceneManager.ForEachScene( delegate(Scene scene) { MainConsole.Instance.Output(String.Format( @@ -1080,7 +1080,7 @@ namespace OpenSim break; case "ratings": - m_sceneManager.ForEachScene( + SceneManager.ForEachScene( delegate(Scene scene) { string rating = ""; @@ -1115,7 +1115,7 @@ namespace OpenSim cdt.AddColumn("IP", 16); cdt.AddColumn("Viewer Name", 24); - m_sceneManager.ForEachScene( + SceneManager.ForEachScene( s => { foreach (AgentCircuitData aCircuit in s.AuthenticateHandler.GetAgentCircuits().Values) @@ -1140,7 +1140,7 @@ namespace OpenSim cdt.AddColumn("Endpoint", 23); cdt.AddColumn("Active?", 7); - m_sceneManager.ForEachScene( + SceneManager.ForEachScene( s => s.ForEachClient( c => cdt.AddRow( s.Name, @@ -1161,11 +1161,11 @@ namespace OpenSim { if (cmdparams.Length > 5) { - m_sceneManager.SaveNamedPrimsToXml2(cmdparams[3], cmdparams[4]); + SceneManager.SaveNamedPrimsToXml2(cmdparams[3], cmdparams[4]); } else { - m_sceneManager.SaveNamedPrimsToXml2("Primitive", DEFAULT_PRIM_BACKUP_FILENAME); + SceneManager.SaveNamedPrimsToXml2("Primitive", DEFAULT_PRIM_BACKUP_FILENAME); } } @@ -1180,11 +1180,11 @@ namespace OpenSim if (cmdparams.Length > 0) { - m_sceneManager.SaveCurrentSceneToXml(cmdparams[2]); + SceneManager.SaveCurrentSceneToXml(cmdparams[2]); } else { - m_sceneManager.SaveCurrentSceneToXml(DEFAULT_PRIM_BACKUP_FILENAME); + SceneManager.SaveCurrentSceneToXml(DEFAULT_PRIM_BACKUP_FILENAME); } } @@ -1221,13 +1221,13 @@ namespace OpenSim MainConsole.Instance.Output(String.Format("loadOffsets = <{0},{1},{2}>",loadOffset.X,loadOffset.Y,loadOffset.Z)); } } - m_sceneManager.LoadCurrentSceneFromXml(cmdparams[2], generateNewIDS, loadOffset); + SceneManager.LoadCurrentSceneFromXml(cmdparams[2], generateNewIDS, loadOffset); } else { try { - m_sceneManager.LoadCurrentSceneFromXml(DEFAULT_PRIM_BACKUP_FILENAME, false, loadOffset); + SceneManager.LoadCurrentSceneFromXml(DEFAULT_PRIM_BACKUP_FILENAME, false, loadOffset); } catch (FileNotFoundException) { @@ -1244,11 +1244,11 @@ namespace OpenSim { if (cmdparams.Length > 2) { - m_sceneManager.SaveCurrentSceneToXml2(cmdparams[2]); + SceneManager.SaveCurrentSceneToXml2(cmdparams[2]); } else { - m_sceneManager.SaveCurrentSceneToXml2(DEFAULT_PRIM_BACKUP_FILENAME); + SceneManager.SaveCurrentSceneToXml2(DEFAULT_PRIM_BACKUP_FILENAME); } } @@ -1263,7 +1263,7 @@ namespace OpenSim { try { - m_sceneManager.LoadCurrentSceneFromXml2(cmdparams[2]); + SceneManager.LoadCurrentSceneFromXml2(cmdparams[2]); } catch (FileNotFoundException) { @@ -1274,7 +1274,7 @@ namespace OpenSim { try { - m_sceneManager.LoadCurrentSceneFromXml2(DEFAULT_PRIM_BACKUP_FILENAME); + SceneManager.LoadCurrentSceneFromXml2(DEFAULT_PRIM_BACKUP_FILENAME); } catch (FileNotFoundException) { @@ -1291,7 +1291,7 @@ namespace OpenSim { try { - m_sceneManager.LoadArchiveToCurrentScene(cmdparams); + SceneManager.LoadArchiveToCurrentScene(cmdparams); } catch (Exception e) { @@ -1305,7 +1305,7 @@ namespace OpenSim /// protected void SaveOar(string module, string[] cmdparams) { - m_sceneManager.SaveCurrentSceneToArchive(cmdparams); + SceneManager.SaveCurrentSceneToArchive(cmdparams); } private static string CombineParams(string[] commandParams, int pos) diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs index 3271555..825c4c4 100644 --- a/OpenSim/Region/Application/OpenSimBase.cs +++ b/OpenSim/Region/Application/OpenSimBase.cs @@ -285,7 +285,7 @@ namespace OpenSim private void HandleCommanderCommand(string module, string[] cmd) { - m_sceneManager.SendCommandToPluginModules(cmd); + SceneManager.SendCommandToPluginModules(cmd); } private void HandleCommanderHelp(string module, string[] cmd) @@ -303,7 +303,10 @@ namespace OpenSim // Called from base.StartUp() m_httpServerPort = m_networkServersInfo.HttpListenerPort; - m_sceneManager.OnRestartSim += handleRestartRegion; + SceneManager.OnRestartSim += handleRestartRegion; + + // Only start the memory watchdog once all regions are ready + SceneManager.OnRegionsReadyStatusChange += sm => MemoryWatchdog.Enabled = sm.AllRegionsReady; } /// @@ -412,7 +415,7 @@ namespace OpenSim // scripting engines. scene.CreateScriptInstances(); - m_sceneManager.Add(scene); + SceneManager.Add(scene); if (m_autoCreateClientStack) { @@ -432,7 +435,6 @@ namespace OpenSim mscene = scene; scene.Start(); - scene.StartScripts(); return clientServer; @@ -561,14 +563,14 @@ namespace OpenSim { // only need to check this if we are not at the // root level - if ((m_sceneManager.CurrentScene != null) && - (m_sceneManager.CurrentScene.RegionInfo.RegionID == scene.RegionInfo.RegionID)) + if ((SceneManager.CurrentScene != null) && + (SceneManager.CurrentScene.RegionInfo.RegionID == scene.RegionInfo.RegionID)) { - m_sceneManager.TrySetCurrentScene(".."); + SceneManager.TrySetCurrentScene(".."); } scene.DeleteAllSceneObjects(); - m_sceneManager.CloseScene(scene); + SceneManager.CloseScene(scene); ShutdownClientServer(scene.RegionInfo); if (!cleanup) @@ -610,7 +612,7 @@ namespace OpenSim public void RemoveRegion(string name, bool cleanUp) { Scene target; - if (m_sceneManager.TryGetScene(name, out target)) + if (SceneManager.TryGetScene(name, out target)) RemoveRegion(target, cleanUp); } @@ -623,13 +625,13 @@ namespace OpenSim { // only need to check this if we are not at the // root level - if ((m_sceneManager.CurrentScene != null) && - (m_sceneManager.CurrentScene.RegionInfo.RegionID == scene.RegionInfo.RegionID)) + if ((SceneManager.CurrentScene != null) && + (SceneManager.CurrentScene.RegionInfo.RegionID == scene.RegionInfo.RegionID)) { - m_sceneManager.TrySetCurrentScene(".."); + SceneManager.TrySetCurrentScene(".."); } - m_sceneManager.CloseScene(scene); + SceneManager.CloseScene(scene); ShutdownClientServer(scene.RegionInfo); } @@ -641,7 +643,7 @@ namespace OpenSim public void CloseRegion(string name) { Scene target; - if (m_sceneManager.TryGetScene(name, out target)) + if (SceneManager.TryGetScene(name, out target)) CloseRegion(target); } @@ -897,7 +899,7 @@ namespace OpenSim try { - m_sceneManager.Close(); + SceneManager.Close(); } catch (Exception e) { @@ -922,7 +924,7 @@ namespace OpenSim /// The first out parameter describing the number of all the avatars in the Region server public void GetAvatarNumber(out int usernum) { - usernum = m_sceneManager.GetCurrentSceneAvatars().Count; + usernum = SceneManager.GetCurrentSceneAvatars().Count; } /// @@ -931,7 +933,7 @@ namespace OpenSim /// The first out parameter describing the number of regions public void GetRegionNumber(out int regionnum) { - regionnum = m_sceneManager.Scenes.Count; + regionnum = SceneManager.Scenes.Count; } /// diff --git a/OpenSim/Region/ClientStack/RegionApplicationBase.cs b/OpenSim/Region/ClientStack/RegionApplicationBase.cs index c4324e8..4672f8a 100644 --- a/OpenSim/Region/ClientStack/RegionApplicationBase.cs +++ b/OpenSim/Region/ClientStack/RegionApplicationBase.cs @@ -53,9 +53,8 @@ namespace OpenSim.Region.ClientStack protected ISimulationDataService m_simulationDataService; protected IEstateDataService m_estateDataService; protected ClientStackManager m_clientStackManager; - protected SceneManager m_sceneManager = new SceneManager(); - public SceneManager SceneManager { get { return m_sceneManager; } } + public SceneManager SceneManager { get; protected set; } public NetworkServersInfo NetServersInfo { get { return m_networkServersInfo; } } public ISimulationDataService SimulationDataService { get { return m_simulationDataService; } } public IEstateDataService EstateDataService { get { return m_estateDataService; } } @@ -77,6 +76,7 @@ namespace OpenSim.Region.ClientStack protected override void StartupSpecific() { + SceneManager = new SceneManager(); m_clientStackManager = CreateClientStackManager(); Initialize(); -- cgit v1.1 From 22aa436648e7cdddefa5fb7263c0fdec294733b5 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 25 Jul 2012 22:33:24 +0100 Subject: Correct churn stat from MB/s from KB/s --- OpenSim/Framework/Statistics/BaseStatsCollector.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim') diff --git a/OpenSim/Framework/Statistics/BaseStatsCollector.cs b/OpenSim/Framework/Statistics/BaseStatsCollector.cs index 28ce650..1fe086c 100644 --- a/OpenSim/Framework/Statistics/BaseStatsCollector.cs +++ b/OpenSim/Framework/Statistics/BaseStatsCollector.cs @@ -50,7 +50,7 @@ namespace OpenSim.Framework.Statistics Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0)); sb.AppendFormat( - "OpenSim object memory churn : {0} KB/s\n", + "OpenSim object memory churn : {0} MB/s\n", Math.Round((MemoryWatchdog.AverageMemoryChurn * 1000) / 1024.0 / 1024, 3)); sb.AppendFormat( -- cgit v1.1 From 227126adb784ed70739f42aec0072bdd8f06de9a Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 25 Jul 2012 22:38:28 +0100 Subject: Add MemoryWatchdog class missing from git master a1e9964 --- OpenSim/Framework/MemoryWatchdog.cs | 129 ++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 OpenSim/Framework/MemoryWatchdog.cs (limited to 'OpenSim') diff --git a/OpenSim/Framework/MemoryWatchdog.cs b/OpenSim/Framework/MemoryWatchdog.cs new file mode 100644 index 0000000..1e93077 --- /dev/null +++ b/OpenSim/Framework/MemoryWatchdog.cs @@ -0,0 +1,129 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Threading; +using log4net; + +namespace OpenSim.Framework +{ + /// + /// Experimental watchdog for memory usage. + /// + public static class MemoryWatchdog + { +// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// Is this watchdog active? + /// + public static bool Enabled + { + get { return m_enabled; } + set + { +// m_log.DebugFormat("[MEMORY WATCHDOG]: Setting MemoryWatchdog.Enabled to {0}", value); + + if (value && !m_enabled) + UpdateLastRecord(GC.GetTotalMemory(false), Util.EnvironmentTickCount()); + + m_enabled = value; + } + } + private static bool m_enabled; + + /// + /// Average memory churn in bytes per millisecond. + /// + public static double AverageMemoryChurn + { + get { if (m_samples.Count > 0) return m_samples.Average(); else return 0; } + } + + /// + /// Maximum number of statistical samples. + /// + /// + /// At the moment this corresponds to 1 minute since the sampling rate is every 2.5 seconds as triggered from + /// the main Watchdog. + /// + private static int m_maxSamples = 24; + + /// + /// Time when the watchdog was last updated. + /// + private static int m_lastUpdateTick; + + /// + /// Memory used at time of last watchdog update. + /// + private static long m_lastUpdateMemory; + + /// + /// Memory churn rate per millisecond. + /// + private static double m_churnRatePerMillisecond; + + /// + /// Historical samples for calculating moving average. + /// + private static Queue m_samples = new Queue(m_maxSamples); + + public static void Update() + { + int now = Util.EnvironmentTickCount(); + long memoryNow = GC.GetTotalMemory(false); + long memoryDiff = memoryNow - m_lastUpdateMemory; + + if (memoryDiff >= 0) + { + if (m_samples.Count >= m_maxSamples) + m_samples.Dequeue(); + + double elapsed = Util.EnvironmentTickCountSubtract(now, m_lastUpdateTick); + + // This should never happen since it's not useful for updates to occur with no time elapsed, but + // protect ourselves from a divide-by-zero just in case. + if (elapsed == 0) + return; + + m_samples.Enqueue(memoryDiff / (double)elapsed); + } + + UpdateLastRecord(memoryNow, now); + } + + private static void UpdateLastRecord(long memoryNow, int timeNow) + { + m_lastUpdateMemory = memoryNow; + m_lastUpdateTick = timeNow; + } + } +} \ No newline at end of file -- cgit v1.1 From 35efa88c26d249d315837fdca0faf643511e1a4e Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 25 Jul 2012 23:11:50 +0100 Subject: Rename OpenSim.Framework.Statistics to OpenSim.Framework.Monitoring. This better reflects the long-term purpose of that project and matches Monitoring modules. --- .../Framework/Monitoring/AssetStatsCollector.cs | 104 +++++ OpenSim/Framework/Monitoring/BaseStatsCollector.cs | 67 +++ .../Monitoring/Interfaces/IPullStatsProvider.cs | 41 ++ .../Monitoring/Interfaces/IStatsCollector.cs | 49 +++ .../Framework/Monitoring/SimExtraStatsCollector.cs | 463 ++++++++++++++++++++ OpenSim/Framework/Monitoring/StatsManager.cs | 65 +++ OpenSim/Framework/Monitoring/UserStatsCollector.cs | 92 ++++ OpenSim/Framework/Servers/BaseOpenSimServer.cs | 2 +- .../Framework/Statistics/AssetStatsCollector.cs | 104 ----- OpenSim/Framework/Statistics/BaseStatsCollector.cs | 68 --- .../Statistics/Interfaces/IPullStatsProvider.cs | 41 -- .../Statistics/Interfaces/IStatsCollector.cs | 49 --- .../Framework/Statistics/SimExtraStatsCollector.cs | 464 --------------------- OpenSim/Framework/Statistics/StatsManager.cs | 65 --- OpenSim/Framework/Statistics/UserStatsCollector.cs | 92 ---- OpenSim/Region/Application/OpenSim.cs | 2 +- OpenSim/Region/Application/OpenSimBase.cs | 2 +- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 2 +- .../Region/ClientStack/Linden/UDP/LLUDPServer.cs | 2 +- .../Avatar/Commands/UserCommandsModule.cs | 2 +- .../Inventory/RemoteXInventoryServiceConnector.cs | 2 +- .../World/Objects/Commands/ObjectCommandsModule.cs | 2 +- .../World/Region/RegionCommandsModule.cs | 2 +- .../Region/Framework/Scenes/RegionStatsHandler.cs | 2 +- .../Region/Framework/Scenes/SimStatsReporter.cs | 2 +- .../Agent/UDP/Linden/LindenUDPInfoModule.cs | 2 +- .../Avatar/Appearance/AppearanceInfoModule.cs | 2 +- .../Avatar/Attachments/AttachmentsCommandModule.cs | 2 +- .../Avatar/Friends/FriendsCommandsModule.cs | 2 +- .../Region/UserStatistics/ActiveConnectionsAJAX.cs | 2 +- OpenSim/Region/UserStatistics/Default_Report.cs | 2 +- OpenSim/Region/UserStatistics/LogLinesAJAX.cs | 2 +- OpenSim/Region/UserStatistics/SimStatsAJAX.cs | 2 +- 33 files changed, 900 insertions(+), 902 deletions(-) create mode 100644 OpenSim/Framework/Monitoring/AssetStatsCollector.cs create mode 100644 OpenSim/Framework/Monitoring/BaseStatsCollector.cs create mode 100644 OpenSim/Framework/Monitoring/Interfaces/IPullStatsProvider.cs create mode 100644 OpenSim/Framework/Monitoring/Interfaces/IStatsCollector.cs create mode 100644 OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs create mode 100644 OpenSim/Framework/Monitoring/StatsManager.cs create mode 100644 OpenSim/Framework/Monitoring/UserStatsCollector.cs delete mode 100644 OpenSim/Framework/Statistics/AssetStatsCollector.cs delete mode 100644 OpenSim/Framework/Statistics/BaseStatsCollector.cs delete mode 100644 OpenSim/Framework/Statistics/Interfaces/IPullStatsProvider.cs delete mode 100644 OpenSim/Framework/Statistics/Interfaces/IStatsCollector.cs delete mode 100644 OpenSim/Framework/Statistics/SimExtraStatsCollector.cs delete mode 100644 OpenSim/Framework/Statistics/StatsManager.cs delete mode 100644 OpenSim/Framework/Statistics/UserStatsCollector.cs (limited to 'OpenSim') diff --git a/OpenSim/Framework/Monitoring/AssetStatsCollector.cs b/OpenSim/Framework/Monitoring/AssetStatsCollector.cs new file mode 100644 index 0000000..2a4d45b --- /dev/null +++ b/OpenSim/Framework/Monitoring/AssetStatsCollector.cs @@ -0,0 +1,104 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Timers; + +namespace OpenSim.Framework.Monitoring +{ + /// + /// Asset service statistics collection + /// + public class AssetStatsCollector : BaseStatsCollector + { + private Timer ageStatsTimer = new Timer(24 * 60 * 60 * 1000); + private DateTime startTime = DateTime.Now; + + private long assetRequestsToday; + private long assetRequestsNotFoundToday; + private long assetRequestsYesterday; + private long assetRequestsNotFoundYesterday; + + public long AssetRequestsToday { get { return assetRequestsToday; } } + public long AssetRequestsNotFoundToday { get { return assetRequestsNotFoundToday; } } + public long AssetRequestsYesterday { get { return assetRequestsYesterday; } } + public long AssetRequestsNotFoundYesterday { get { return assetRequestsNotFoundYesterday; } } + + public AssetStatsCollector() + { + ageStatsTimer.Elapsed += new ElapsedEventHandler(OnAgeing); + ageStatsTimer.Enabled = true; + } + + private void OnAgeing(object source, ElapsedEventArgs e) + { + assetRequestsYesterday = assetRequestsToday; + + // There is a possibility that an asset request could occur between the execution of these + // two statements. But we're better off without the synchronization overhead. + assetRequestsToday = 0; + + assetRequestsNotFoundYesterday = assetRequestsNotFoundToday; + assetRequestsNotFoundToday = 0; + } + + /// + /// Record that an asset request failed to find an asset + /// + public void AddNotFoundRequest() + { + assetRequestsNotFoundToday++; + } + + /// + /// Record that a request was made to the asset server + /// + public void AddRequest() + { + assetRequestsToday++; + } + + /// + /// Report back collected statistical information. + /// + /// + override public string Report() + { + double elapsedHours = (DateTime.Now - startTime).TotalHours; + if (elapsedHours <= 0) { elapsedHours = 1; } // prevent divide by zero + + long assetRequestsTodayPerHour = (long)Math.Round(AssetRequestsToday / elapsedHours); + long assetRequestsYesterdayPerHour = (long)Math.Round(AssetRequestsYesterday / 24.0); + + return string.Format( +@"Asset requests today : {0} ({1} per hour) of which {2} were not found +Asset requests yesterday : {3} ({4} per hour) of which {5} were not found", + AssetRequestsToday, assetRequestsTodayPerHour, AssetRequestsNotFoundToday, + AssetRequestsYesterday, assetRequestsYesterdayPerHour, AssetRequestsNotFoundYesterday); + } + } +} diff --git a/OpenSim/Framework/Monitoring/BaseStatsCollector.cs b/OpenSim/Framework/Monitoring/BaseStatsCollector.cs new file mode 100644 index 0000000..57a63ef --- /dev/null +++ b/OpenSim/Framework/Monitoring/BaseStatsCollector.cs @@ -0,0 +1,67 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Diagnostics; +using System.Text; +using OpenMetaverse; +using OpenMetaverse.StructuredData; + +namespace OpenSim.Framework.Monitoring +{ + /// + /// Statistics which all collectors are interested in reporting + /// + public class BaseStatsCollector : IStatsCollector + { + public virtual string Report() + { + StringBuilder sb = new StringBuilder(Environment.NewLine); + sb.Append("MEMORY STATISTICS"); + sb.Append(Environment.NewLine); + + sb.AppendFormat( + "Allocated to OpenSim objects: {0} MB\n", + Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0)); + + sb.AppendFormat( + "OpenSim object memory churn : {0} MB/s\n", + Math.Round((MemoryWatchdog.AverageMemoryChurn * 1000) / 1024.0 / 1024, 3)); + + sb.AppendFormat( + "Process memory : {0} MB\n", + Math.Round(Process.GetCurrentProcess().WorkingSet64 / 1024.0 / 1024.0)); + + return sb.ToString(); + } + + public virtual string XReport(string uptime, string version) + { + return (string) Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0).ToString() ; + } + } +} diff --git a/OpenSim/Framework/Monitoring/Interfaces/IPullStatsProvider.cs b/OpenSim/Framework/Monitoring/Interfaces/IPullStatsProvider.cs new file mode 100644 index 0000000..86a6620 --- /dev/null +++ b/OpenSim/Framework/Monitoring/Interfaces/IPullStatsProvider.cs @@ -0,0 +1,41 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +namespace OpenSim.Framework.Monitoring.Interfaces +{ + /// + /// Implemented by objects which allow statistical information to be pulled from them. + /// + public interface IPullStatsProvider + { + /// + /// Provide statistical information. Only temporary one long string. + /// + /// + string GetStats(); + } +} diff --git a/OpenSim/Framework/Monitoring/Interfaces/IStatsCollector.cs b/OpenSim/Framework/Monitoring/Interfaces/IStatsCollector.cs new file mode 100644 index 0000000..99f75e3 --- /dev/null +++ b/OpenSim/Framework/Monitoring/Interfaces/IStatsCollector.cs @@ -0,0 +1,49 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +namespace OpenSim.Framework.Monitoring +{ + /// + /// Implemented by classes which collect up non-viewer statistical information + /// + public interface IStatsCollector + { + /// + /// Report back collected statistical information. + /// + /// + string Report(); + + /// + /// Report back collected statistical information in json + /// + /// + /// A + /// + string XReport(string uptime, string version); + } +} diff --git a/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs new file mode 100644 index 0000000..cdd7cc7 --- /dev/null +++ b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs @@ -0,0 +1,463 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Text; +using OpenMetaverse; +using OpenMetaverse.StructuredData; +using OpenSim.Framework.Monitoring.Interfaces; + +namespace OpenSim.Framework.Monitoring +{ + /// + /// Collects sim statistics which aren't already being collected for the linden viewer's statistics pane + /// + public class SimExtraStatsCollector : BaseStatsCollector + { + private long abnormalClientThreadTerminations; + +// private long assetsInCache; +// private long texturesInCache; +// private long assetCacheMemoryUsage; +// private long textureCacheMemoryUsage; +// private TimeSpan assetRequestTimeAfterCacheMiss; +// private long blockedMissingTextureRequests; + +// private long assetServiceRequestFailures; +// private long inventoryServiceRetrievalFailures; + + private volatile float timeDilation; + private volatile float simFps; + private volatile float physicsFps; + private volatile float agentUpdates; + private volatile float rootAgents; + private volatile float childAgents; + private volatile float totalPrims; + private volatile float activePrims; + private volatile float totalFrameTime; + private volatile float netFrameTime; + private volatile float physicsFrameTime; + private volatile float otherFrameTime; + private volatile float imageFrameTime; + private volatile float inPacketsPerSecond; + private volatile float outPacketsPerSecond; + private volatile float unackedBytes; + private volatile float agentFrameTime; + private volatile float pendingDownloads; + private volatile float pendingUploads; + private volatile float activeScripts; + private volatile float scriptLinesPerSecond; + + /// + /// Number of times that a client thread terminated because of an exception + /// + public long AbnormalClientThreadTerminations { get { return abnormalClientThreadTerminations; } } + +// /// +// /// These statistics are being collected by push rather than pull. Pull would be simpler, but I had the +// /// notion of providing some flow statistics (which pull wouldn't give us). Though admittedly these +// /// haven't yet been implemented... +// /// +// public long AssetsInCache { get { return assetsInCache; } } +// +// /// +// /// Currently unused +// /// +// public long TexturesInCache { get { return texturesInCache; } } +// +// /// +// /// Currently misleading since we can't currently subtract removed asset memory usage without a performance hit +// /// +// public long AssetCacheMemoryUsage { get { return assetCacheMemoryUsage; } } +// +// /// +// /// Currently unused +// /// +// public long TextureCacheMemoryUsage { get { return textureCacheMemoryUsage; } } + + public float TimeDilation { get { return timeDilation; } } + public float SimFps { get { return simFps; } } + public float PhysicsFps { get { return physicsFps; } } + public float AgentUpdates { get { return agentUpdates; } } + public float RootAgents { get { return rootAgents; } } + public float ChildAgents { get { return childAgents; } } + public float TotalPrims { get { return totalPrims; } } + public float ActivePrims { get { return activePrims; } } + public float TotalFrameTime { get { return totalFrameTime; } } + public float NetFrameTime { get { return netFrameTime; } } + public float PhysicsFrameTime { get { return physicsFrameTime; } } + public float OtherFrameTime { get { return otherFrameTime; } } + public float ImageFrameTime { get { return imageFrameTime; } } + public float InPacketsPerSecond { get { return inPacketsPerSecond; } } + public float OutPacketsPerSecond { get { return outPacketsPerSecond; } } + public float UnackedBytes { get { return unackedBytes; } } + public float AgentFrameTime { get { return agentFrameTime; } } + public float PendingDownloads { get { return pendingDownloads; } } + public float PendingUploads { get { return pendingUploads; } } + public float ActiveScripts { get { return activeScripts; } } + public float ScriptLinesPerSecond { get { return scriptLinesPerSecond; } } + +// /// +// /// This is the time it took for the last asset request made in response to a cache miss. +// /// +// public TimeSpan AssetRequestTimeAfterCacheMiss { get { return assetRequestTimeAfterCacheMiss; } } +// +// /// +// /// Number of persistent requests for missing textures we have started blocking from clients. To some extent +// /// this is just a temporary statistic to keep this problem in view - the root cause of this lies either +// /// in a mishandling of the reply protocol, related to avatar appearance or may even originate in graphics +// /// driver bugs on clients (though this seems less likely). +// /// +// public long BlockedMissingTextureRequests { get { return blockedMissingTextureRequests; } } +// +// /// +// /// Record the number of times that an asset request has failed. Failures are effectively exceptions, such as +// /// request timeouts. If an asset service replies that a particular asset cannot be found, this is not counted +// /// as a failure +// /// +// public long AssetServiceRequestFailures { get { return assetServiceRequestFailures; } } + + /// + /// Number of known failures to retrieve avatar inventory from the inventory service. This does not + /// cover situations where the inventory service accepts the request but never returns any data, since + /// we do not yet timeout this situation. + /// + /// Commented out because we do not cache inventory at this point +// public long InventoryServiceRetrievalFailures { get { return inventoryServiceRetrievalFailures; } } + + /// + /// Retrieve the total frame time (in ms) of the last frame + /// + //public float TotalFrameTime { get { return totalFrameTime; } } + + /// + /// Retrieve the physics update component (in ms) of the last frame + /// + //public float PhysicsFrameTime { get { return physicsFrameTime; } } + + /// + /// Retain a dictionary of all packet queues stats reporters + /// + private IDictionary packetQueueStatsCollectors + = new Dictionary(); + + public void AddAbnormalClientThreadTermination() + { + abnormalClientThreadTerminations++; + } + +// public void AddAsset(AssetBase asset) +// { +// assetsInCache++; +// //assetCacheMemoryUsage += asset.Data.Length; +// } +// +// public void RemoveAsset(UUID uuid) +// { +// assetsInCache--; +// } +// +// public void AddTexture(AssetBase image) +// { +// if (image.Data != null) +// { +// texturesInCache++; +// +// // This could have been a pull stat, though there was originally a nebulous idea to measure flow rates +// textureCacheMemoryUsage += image.Data.Length; +// } +// } +// +// /// +// /// Signal that the asset cache has been cleared. +// /// +// public void ClearAssetCacheStatistics() +// { +// assetsInCache = 0; +// assetCacheMemoryUsage = 0; +// texturesInCache = 0; +// textureCacheMemoryUsage = 0; +// } +// +// public void AddAssetRequestTimeAfterCacheMiss(TimeSpan ts) +// { +// assetRequestTimeAfterCacheMiss = ts; +// } +// +// public void AddBlockedMissingTextureRequest() +// { +// blockedMissingTextureRequests++; +// } +// +// public void AddAssetServiceRequestFailure() +// { +// assetServiceRequestFailures++; +// } + +// public void AddInventoryServiceRetrievalFailure() +// { +// inventoryServiceRetrievalFailures++; +// } + + /// + /// Register as a packet queue stats provider + /// + /// An agent UUID + /// + public void RegisterPacketQueueStatsProvider(UUID uuid, IPullStatsProvider provider) + { + lock (packetQueueStatsCollectors) + { + // FIXME: If the region service is providing more than one region, then the child and root agent + // queues are wrongly replacing each other here. + packetQueueStatsCollectors[uuid] = new PacketQueueStatsCollector(provider); + } + } + + /// + /// Deregister a packet queue stats provider + /// + /// An agent UUID + public void DeregisterPacketQueueStatsProvider(UUID uuid) + { + lock (packetQueueStatsCollectors) + { + packetQueueStatsCollectors.Remove(uuid); + } + } + + /// + /// This is the method on which the classic sim stats reporter (which collects stats for + /// client purposes) sends information to listeners. + /// + /// + public void ReceiveClassicSimStatsPacket(SimStats stats) + { + // FIXME: SimStats shouldn't allow an arbitrary stat packing order (which is inherited from the original + // SimStatsPacket that was being used). + timeDilation = stats.StatsBlock[0].StatValue; + simFps = stats.StatsBlock[1].StatValue; + physicsFps = stats.StatsBlock[2].StatValue; + agentUpdates = stats.StatsBlock[3].StatValue; + rootAgents = stats.StatsBlock[4].StatValue; + childAgents = stats.StatsBlock[5].StatValue; + totalPrims = stats.StatsBlock[6].StatValue; + activePrims = stats.StatsBlock[7].StatValue; + totalFrameTime = stats.StatsBlock[8].StatValue; + netFrameTime = stats.StatsBlock[9].StatValue; + physicsFrameTime = stats.StatsBlock[10].StatValue; + otherFrameTime = stats.StatsBlock[11].StatValue; + imageFrameTime = stats.StatsBlock[12].StatValue; + inPacketsPerSecond = stats.StatsBlock[13].StatValue; + outPacketsPerSecond = stats.StatsBlock[14].StatValue; + unackedBytes = stats.StatsBlock[15].StatValue; + agentFrameTime = stats.StatsBlock[16].StatValue; + pendingDownloads = stats.StatsBlock[17].StatValue; + pendingUploads = stats.StatsBlock[18].StatValue; + activeScripts = stats.StatsBlock[19].StatValue; + scriptLinesPerSecond = stats.StatsBlock[20].StatValue; + } + + /// + /// Report back collected statistical information. + /// + /// + public override string Report() + { + StringBuilder sb = new StringBuilder(Environment.NewLine); +// sb.Append("ASSET STATISTICS"); +// sb.Append(Environment.NewLine); + + /* + sb.Append( + string.Format( +@"Asset cache contains {0,6} non-texture assets using {1,10} K +Texture cache contains {2,6} texture assets using {3,10} K +Latest asset request time after cache miss: {4}s +Blocked client requests for missing textures: {5} +Asset service request failures: {6}"+ Environment.NewLine, + AssetsInCache, Math.Round(AssetCacheMemoryUsage / 1024.0), + TexturesInCache, Math.Round(TextureCacheMemoryUsage / 1024.0), + assetRequestTimeAfterCacheMiss.Milliseconds / 1000.0, + BlockedMissingTextureRequests, + AssetServiceRequestFailures)); + */ + + /* + sb.Append( + string.Format( +@"Asset cache contains {0,6} assets +Latest asset request time after cache miss: {1}s +Blocked client requests for missing textures: {2} +Asset service request failures: {3}" + Environment.NewLine, + AssetsInCache, + assetRequestTimeAfterCacheMiss.Milliseconds / 1000.0, + BlockedMissingTextureRequests, + AssetServiceRequestFailures)); + */ + + sb.Append(Environment.NewLine); + sb.Append("CONNECTION STATISTICS"); + sb.Append(Environment.NewLine); + sb.Append( + string.Format( + "Abnormal client thread terminations: {0}" + Environment.NewLine, + abnormalClientThreadTerminations)); + +// sb.Append(Environment.NewLine); +// sb.Append("INVENTORY STATISTICS"); +// sb.Append(Environment.NewLine); +// sb.Append( +// string.Format( +// "Initial inventory caching failures: {0}" + Environment.NewLine, +// InventoryServiceRetrievalFailures)); + + sb.Append(Environment.NewLine); + sb.Append("FRAME STATISTICS"); + sb.Append(Environment.NewLine); + sb.Append("Dilatn SimFPS PhyFPS AgntUp RootAg ChldAg Prims AtvPrm AtvScr ScrLPS"); + sb.Append(Environment.NewLine); + sb.Append( + string.Format( + "{0,6:0.00} {1,6:0} {2,6:0.0} {3,6:0.0} {4,6:0} {5,6:0} {6,6:0} {7,6:0} {8,6:0} {9,6:0}", + timeDilation, simFps, physicsFps, agentUpdates, rootAgents, + childAgents, totalPrims, activePrims, activeScripts, scriptLinesPerSecond)); + + sb.Append(Environment.NewLine); + sb.Append(Environment.NewLine); + // There is no script frame time currently because we don't yet collect it + sb.Append("PktsIn PktOut PendDl PendUl UnackB TotlFt NetFt PhysFt OthrFt AgntFt ImgsFt"); + sb.Append(Environment.NewLine); + sb.Append( + string.Format( + "{0,6:0} {1,6:0} {2,6:0} {3,6:0} {4,6:0} {5,6:0.0} {6,6:0.0} {7,6:0.0} {8,6:0.0} {9,6:0.0} {10,6:0.0}", + inPacketsPerSecond, outPacketsPerSecond, pendingDownloads, pendingUploads, unackedBytes, totalFrameTime, + netFrameTime, physicsFrameTime, otherFrameTime, agentFrameTime, imageFrameTime)); + sb.Append(Environment.NewLine); + + /* + sb.Append(Environment.NewLine); + sb.Append("PACKET QUEUE STATISTICS"); + sb.Append(Environment.NewLine); + sb.Append("Agent UUID "); + sb.Append( + string.Format( + " {0,7} {1,7} {2,7} {3,7} {4,7} {5,7} {6,7} {7,7} {8,7} {9,7}", + "Send", "In", "Out", "Resend", "Land", "Wind", "Cloud", "Task", "Texture", "Asset")); + sb.Append(Environment.NewLine); + + foreach (UUID key in packetQueueStatsCollectors.Keys) + { + sb.Append(string.Format("{0}: ", key)); + sb.Append(packetQueueStatsCollectors[key].Report()); + sb.Append(Environment.NewLine); + } + */ + + sb.Append(base.Report()); + + return sb.ToString(); + } + + /// + /// Report back collected statistical information as json serialization. + /// + /// + public override string XReport(string uptime, string version) + { + OSDMap args = new OSDMap(30); +// args["AssetsInCache"] = OSD.FromString (String.Format ("{0:0.##}", AssetsInCache)); +// args["TimeAfterCacheMiss"] = OSD.FromString (String.Format ("{0:0.##}", +// assetRequestTimeAfterCacheMiss.Milliseconds / 1000.0)); +// args["BlockedMissingTextureRequests"] = OSD.FromString (String.Format ("{0:0.##}", +// BlockedMissingTextureRequests)); +// args["AssetServiceRequestFailures"] = OSD.FromString (String.Format ("{0:0.##}", +// AssetServiceRequestFailures)); +// args["abnormalClientThreadTerminations"] = OSD.FromString (String.Format ("{0:0.##}", +// abnormalClientThreadTerminations)); +// args["InventoryServiceRetrievalFailures"] = OSD.FromString (String.Format ("{0:0.##}", +// InventoryServiceRetrievalFailures)); + args["Dilatn"] = OSD.FromString (String.Format ("{0:0.##}", timeDilation)); + args["SimFPS"] = OSD.FromString (String.Format ("{0:0.##}", simFps)); + args["PhyFPS"] = OSD.FromString (String.Format ("{0:0.##}", physicsFps)); + args["AgntUp"] = OSD.FromString (String.Format ("{0:0.##}", agentUpdates)); + args["RootAg"] = OSD.FromString (String.Format ("{0:0.##}", rootAgents)); + args["ChldAg"] = OSD.FromString (String.Format ("{0:0.##}", childAgents)); + args["Prims"] = OSD.FromString (String.Format ("{0:0.##}", totalPrims)); + args["AtvPrm"] = OSD.FromString (String.Format ("{0:0.##}", activePrims)); + args["AtvScr"] = OSD.FromString (String.Format ("{0:0.##}", activeScripts)); + args["ScrLPS"] = OSD.FromString (String.Format ("{0:0.##}", scriptLinesPerSecond)); + args["PktsIn"] = OSD.FromString (String.Format ("{0:0.##}", inPacketsPerSecond)); + args["PktOut"] = OSD.FromString (String.Format ("{0:0.##}", outPacketsPerSecond)); + args["PendDl"] = OSD.FromString (String.Format ("{0:0.##}", pendingDownloads)); + args["PendUl"] = OSD.FromString (String.Format ("{0:0.##}", pendingUploads)); + args["UnackB"] = OSD.FromString (String.Format ("{0:0.##}", unackedBytes)); + args["TotlFt"] = OSD.FromString (String.Format ("{0:0.##}", totalFrameTime)); + args["NetFt"] = OSD.FromString (String.Format ("{0:0.##}", netFrameTime)); + args["PhysFt"] = OSD.FromString (String.Format ("{0:0.##}", physicsFrameTime)); + args["OthrFt"] = OSD.FromString (String.Format ("{0:0.##}", otherFrameTime)); + args["AgntFt"] = OSD.FromString (String.Format ("{0:0.##}", agentFrameTime)); + args["ImgsFt"] = OSD.FromString (String.Format ("{0:0.##}", imageFrameTime)); + args["Memory"] = OSD.FromString (base.XReport (uptime, version)); + args["Uptime"] = OSD.FromString (uptime); + args["Version"] = OSD.FromString (version); + + string strBuffer = ""; + strBuffer = OSDParser.SerializeJsonString(args); + + return strBuffer; + } + } + + /// + /// Pull packet queue stats from packet queues and report + /// + public class PacketQueueStatsCollector : IStatsCollector + { + private IPullStatsProvider m_statsProvider; + + public PacketQueueStatsCollector(IPullStatsProvider provider) + { + m_statsProvider = provider; + } + + /// + /// Report back collected statistical information. + /// + /// + public string Report() + { + return m_statsProvider.GetStats(); + } + + public string XReport(string uptime, string version) + { + return ""; + } + } +} diff --git a/OpenSim/Framework/Monitoring/StatsManager.cs b/OpenSim/Framework/Monitoring/StatsManager.cs new file mode 100644 index 0000000..d78fa6a --- /dev/null +++ b/OpenSim/Framework/Monitoring/StatsManager.cs @@ -0,0 +1,65 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +namespace OpenSim.Framework.Monitoring +{ + /// + /// Singleton used to provide access to statistics reporters + /// + public class StatsManager + { + private static AssetStatsCollector assetStats; + private static UserStatsCollector userStats; + private static SimExtraStatsCollector simExtraStats = new SimExtraStatsCollector(); + + public static AssetStatsCollector AssetStats { get { return assetStats; } } + public static UserStatsCollector UserStats { get { return userStats; } } + public static SimExtraStatsCollector SimExtraStats { get { return simExtraStats; } } + + /// + /// Start collecting statistics related to assets. + /// Should only be called once. + /// + public static AssetStatsCollector StartCollectingAssetStats() + { + assetStats = new AssetStatsCollector(); + + return assetStats; + } + + /// + /// Start collecting statistics related to users. + /// Should only be called once. + /// + public static UserStatsCollector StartCollectingUserStats() + { + userStats = new UserStatsCollector(); + + return userStats; + } + } +} \ No newline at end of file diff --git a/OpenSim/Framework/Monitoring/UserStatsCollector.cs b/OpenSim/Framework/Monitoring/UserStatsCollector.cs new file mode 100644 index 0000000..e89c8e6 --- /dev/null +++ b/OpenSim/Framework/Monitoring/UserStatsCollector.cs @@ -0,0 +1,92 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System.Timers; + +namespace OpenSim.Framework.Monitoring +{ + /// + /// Collects user service statistics + /// + public class UserStatsCollector : BaseStatsCollector + { + private Timer ageStatsTimer = new Timer(24 * 60 * 60 * 1000); + + private int successfulLoginsToday; + public int SuccessfulLoginsToday { get { return successfulLoginsToday; } } + + private int successfulLoginsYesterday; + public int SuccessfulLoginsYesterday { get { return successfulLoginsYesterday; } } + + private int successfulLogins; + public int SuccessfulLogins { get { return successfulLogins; } } + + private int logouts; + public int Logouts { get { return logouts; } } + + public UserStatsCollector() + { + ageStatsTimer.Elapsed += new ElapsedEventHandler(OnAgeing); + ageStatsTimer.Enabled = true; + } + + private void OnAgeing(object source, ElapsedEventArgs e) + { + successfulLoginsYesterday = successfulLoginsToday; + + // There is a possibility that an asset request could occur between the execution of these + // two statements. But we're better off without the synchronization overhead. + successfulLoginsToday = 0; + } + + /// + /// Record a successful login + /// + public void AddSuccessfulLogin() + { + successfulLogins++; + successfulLoginsToday++; + } + + public void AddLogout() + { + logouts++; + } + + /// + /// Report back collected statistical information. + /// + /// + override public string Report() + { + return string.Format( +@"Successful logins total : {0}, today : {1}, yesterday : {2} + Logouts total : {3}", + SuccessfulLogins, SuccessfulLoginsToday, SuccessfulLoginsYesterday, Logouts); + } + } +} diff --git a/OpenSim/Framework/Servers/BaseOpenSimServer.cs b/OpenSim/Framework/Servers/BaseOpenSimServer.cs index 14d8b0c..ab8d95a 100644 --- a/OpenSim/Framework/Servers/BaseOpenSimServer.cs +++ b/OpenSim/Framework/Servers/BaseOpenSimServer.cs @@ -42,7 +42,7 @@ using OpenSim.Framework; using OpenSim.Framework.Console; using OpenSim.Framework.Servers; using OpenSim.Framework.Servers.HttpServer; -using OpenSim.Framework.Statistics; +using OpenSim.Framework.Monitoring; using Timer=System.Timers.Timer; using OpenMetaverse; diff --git a/OpenSim/Framework/Statistics/AssetStatsCollector.cs b/OpenSim/Framework/Statistics/AssetStatsCollector.cs deleted file mode 100644 index 7082ef3..0000000 --- a/OpenSim/Framework/Statistics/AssetStatsCollector.cs +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Timers; - -namespace OpenSim.Framework.Statistics -{ - /// - /// Asset service statistics collection - /// - public class AssetStatsCollector : BaseStatsCollector - { - private Timer ageStatsTimer = new Timer(24 * 60 * 60 * 1000); - private DateTime startTime = DateTime.Now; - - private long assetRequestsToday; - private long assetRequestsNotFoundToday; - private long assetRequestsYesterday; - private long assetRequestsNotFoundYesterday; - - public long AssetRequestsToday { get { return assetRequestsToday; } } - public long AssetRequestsNotFoundToday { get { return assetRequestsNotFoundToday; } } - public long AssetRequestsYesterday { get { return assetRequestsYesterday; } } - public long AssetRequestsNotFoundYesterday { get { return assetRequestsNotFoundYesterday; } } - - public AssetStatsCollector() - { - ageStatsTimer.Elapsed += new ElapsedEventHandler(OnAgeing); - ageStatsTimer.Enabled = true; - } - - private void OnAgeing(object source, ElapsedEventArgs e) - { - assetRequestsYesterday = assetRequestsToday; - - // There is a possibility that an asset request could occur between the execution of these - // two statements. But we're better off without the synchronization overhead. - assetRequestsToday = 0; - - assetRequestsNotFoundYesterday = assetRequestsNotFoundToday; - assetRequestsNotFoundToday = 0; - } - - /// - /// Record that an asset request failed to find an asset - /// - public void AddNotFoundRequest() - { - assetRequestsNotFoundToday++; - } - - /// - /// Record that a request was made to the asset server - /// - public void AddRequest() - { - assetRequestsToday++; - } - - /// - /// Report back collected statistical information. - /// - /// - override public string Report() - { - double elapsedHours = (DateTime.Now - startTime).TotalHours; - if (elapsedHours <= 0) { elapsedHours = 1; } // prevent divide by zero - - long assetRequestsTodayPerHour = (long)Math.Round(AssetRequestsToday / elapsedHours); - long assetRequestsYesterdayPerHour = (long)Math.Round(AssetRequestsYesterday / 24.0); - - return string.Format( -@"Asset requests today : {0} ({1} per hour) of which {2} were not found -Asset requests yesterday : {3} ({4} per hour) of which {5} were not found", - AssetRequestsToday, assetRequestsTodayPerHour, AssetRequestsNotFoundToday, - AssetRequestsYesterday, assetRequestsYesterdayPerHour, AssetRequestsNotFoundYesterday); - } - } -} diff --git a/OpenSim/Framework/Statistics/BaseStatsCollector.cs b/OpenSim/Framework/Statistics/BaseStatsCollector.cs deleted file mode 100644 index 1fe086c..0000000 --- a/OpenSim/Framework/Statistics/BaseStatsCollector.cs +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Diagnostics; -using System.Text; -using OpenMetaverse; -using OpenMetaverse.StructuredData; - - -namespace OpenSim.Framework.Statistics -{ - /// - /// Statistics which all collectors are interested in reporting - /// - public class BaseStatsCollector : IStatsCollector - { - public virtual string Report() - { - StringBuilder sb = new StringBuilder(Environment.NewLine); - sb.Append("MEMORY STATISTICS"); - sb.Append(Environment.NewLine); - - sb.AppendFormat( - "Allocated to OpenSim objects: {0} MB\n", - Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0)); - - sb.AppendFormat( - "OpenSim object memory churn : {0} MB/s\n", - Math.Round((MemoryWatchdog.AverageMemoryChurn * 1000) / 1024.0 / 1024, 3)); - - sb.AppendFormat( - "Process memory : {0} MB\n", - Math.Round(Process.GetCurrentProcess().WorkingSet64 / 1024.0 / 1024.0)); - - return sb.ToString(); - } - - public virtual string XReport(string uptime, string version) - { - return (string) Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0).ToString() ; - } - } -} diff --git a/OpenSim/Framework/Statistics/Interfaces/IPullStatsProvider.cs b/OpenSim/Framework/Statistics/Interfaces/IPullStatsProvider.cs deleted file mode 100644 index 430e580..0000000 --- a/OpenSim/Framework/Statistics/Interfaces/IPullStatsProvider.cs +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -namespace OpenSim.Framework.Statistics.Interfaces -{ - /// - /// Implemented by objects which allow statistical information to be pulled from them. - /// - public interface IPullStatsProvider - { - /// - /// Provide statistical information. Only temporary one long string. - /// - /// - string GetStats(); - } -} diff --git a/OpenSim/Framework/Statistics/Interfaces/IStatsCollector.cs b/OpenSim/Framework/Statistics/Interfaces/IStatsCollector.cs deleted file mode 100644 index 477bbb3..0000000 --- a/OpenSim/Framework/Statistics/Interfaces/IStatsCollector.cs +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -namespace OpenSim.Framework.Statistics -{ - /// - /// Implemented by classes which collect up non-viewer statistical information - /// - public interface IStatsCollector - { - /// - /// Report back collected statistical information. - /// - /// - string Report(); - - /// - /// Report back collected statistical information in json - /// - /// - /// A - /// - string XReport(string uptime, string version); - } -} diff --git a/OpenSim/Framework/Statistics/SimExtraStatsCollector.cs b/OpenSim/Framework/Statistics/SimExtraStatsCollector.cs deleted file mode 100644 index a506e3b..0000000 --- a/OpenSim/Framework/Statistics/SimExtraStatsCollector.cs +++ /dev/null @@ -1,464 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Text; - -using OpenMetaverse; -using OpenSim.Framework.Statistics.Interfaces; -using OpenMetaverse.StructuredData; - -namespace OpenSim.Framework.Statistics -{ - /// - /// Collects sim statistics which aren't already being collected for the linden viewer's statistics pane - /// - public class SimExtraStatsCollector : BaseStatsCollector - { - private long abnormalClientThreadTerminations; - -// private long assetsInCache; -// private long texturesInCache; -// private long assetCacheMemoryUsage; -// private long textureCacheMemoryUsage; -// private TimeSpan assetRequestTimeAfterCacheMiss; -// private long blockedMissingTextureRequests; - -// private long assetServiceRequestFailures; -// private long inventoryServiceRetrievalFailures; - - private volatile float timeDilation; - private volatile float simFps; - private volatile float physicsFps; - private volatile float agentUpdates; - private volatile float rootAgents; - private volatile float childAgents; - private volatile float totalPrims; - private volatile float activePrims; - private volatile float totalFrameTime; - private volatile float netFrameTime; - private volatile float physicsFrameTime; - private volatile float otherFrameTime; - private volatile float imageFrameTime; - private volatile float inPacketsPerSecond; - private volatile float outPacketsPerSecond; - private volatile float unackedBytes; - private volatile float agentFrameTime; - private volatile float pendingDownloads; - private volatile float pendingUploads; - private volatile float activeScripts; - private volatile float scriptLinesPerSecond; - - /// - /// Number of times that a client thread terminated because of an exception - /// - public long AbnormalClientThreadTerminations { get { return abnormalClientThreadTerminations; } } - -// /// -// /// These statistics are being collected by push rather than pull. Pull would be simpler, but I had the -// /// notion of providing some flow statistics (which pull wouldn't give us). Though admittedly these -// /// haven't yet been implemented... -// /// -// public long AssetsInCache { get { return assetsInCache; } } -// -// /// -// /// Currently unused -// /// -// public long TexturesInCache { get { return texturesInCache; } } -// -// /// -// /// Currently misleading since we can't currently subtract removed asset memory usage without a performance hit -// /// -// public long AssetCacheMemoryUsage { get { return assetCacheMemoryUsage; } } -// -// /// -// /// Currently unused -// /// -// public long TextureCacheMemoryUsage { get { return textureCacheMemoryUsage; } } - - public float TimeDilation { get { return timeDilation; } } - public float SimFps { get { return simFps; } } - public float PhysicsFps { get { return physicsFps; } } - public float AgentUpdates { get { return agentUpdates; } } - public float RootAgents { get { return rootAgents; } } - public float ChildAgents { get { return childAgents; } } - public float TotalPrims { get { return totalPrims; } } - public float ActivePrims { get { return activePrims; } } - public float TotalFrameTime { get { return totalFrameTime; } } - public float NetFrameTime { get { return netFrameTime; } } - public float PhysicsFrameTime { get { return physicsFrameTime; } } - public float OtherFrameTime { get { return otherFrameTime; } } - public float ImageFrameTime { get { return imageFrameTime; } } - public float InPacketsPerSecond { get { return inPacketsPerSecond; } } - public float OutPacketsPerSecond { get { return outPacketsPerSecond; } } - public float UnackedBytes { get { return unackedBytes; } } - public float AgentFrameTime { get { return agentFrameTime; } } - public float PendingDownloads { get { return pendingDownloads; } } - public float PendingUploads { get { return pendingUploads; } } - public float ActiveScripts { get { return activeScripts; } } - public float ScriptLinesPerSecond { get { return scriptLinesPerSecond; } } - -// /// -// /// This is the time it took for the last asset request made in response to a cache miss. -// /// -// public TimeSpan AssetRequestTimeAfterCacheMiss { get { return assetRequestTimeAfterCacheMiss; } } -// -// /// -// /// Number of persistent requests for missing textures we have started blocking from clients. To some extent -// /// this is just a temporary statistic to keep this problem in view - the root cause of this lies either -// /// in a mishandling of the reply protocol, related to avatar appearance or may even originate in graphics -// /// driver bugs on clients (though this seems less likely). -// /// -// public long BlockedMissingTextureRequests { get { return blockedMissingTextureRequests; } } -// -// /// -// /// Record the number of times that an asset request has failed. Failures are effectively exceptions, such as -// /// request timeouts. If an asset service replies that a particular asset cannot be found, this is not counted -// /// as a failure -// /// -// public long AssetServiceRequestFailures { get { return assetServiceRequestFailures; } } - - /// - /// Number of known failures to retrieve avatar inventory from the inventory service. This does not - /// cover situations where the inventory service accepts the request but never returns any data, since - /// we do not yet timeout this situation. - /// - /// Commented out because we do not cache inventory at this point -// public long InventoryServiceRetrievalFailures { get { return inventoryServiceRetrievalFailures; } } - - /// - /// Retrieve the total frame time (in ms) of the last frame - /// - //public float TotalFrameTime { get { return totalFrameTime; } } - - /// - /// Retrieve the physics update component (in ms) of the last frame - /// - //public float PhysicsFrameTime { get { return physicsFrameTime; } } - - /// - /// Retain a dictionary of all packet queues stats reporters - /// - private IDictionary packetQueueStatsCollectors - = new Dictionary(); - - public void AddAbnormalClientThreadTermination() - { - abnormalClientThreadTerminations++; - } - -// public void AddAsset(AssetBase asset) -// { -// assetsInCache++; -// //assetCacheMemoryUsage += asset.Data.Length; -// } -// -// public void RemoveAsset(UUID uuid) -// { -// assetsInCache--; -// } -// -// public void AddTexture(AssetBase image) -// { -// if (image.Data != null) -// { -// texturesInCache++; -// -// // This could have been a pull stat, though there was originally a nebulous idea to measure flow rates -// textureCacheMemoryUsage += image.Data.Length; -// } -// } -// -// /// -// /// Signal that the asset cache has been cleared. -// /// -// public void ClearAssetCacheStatistics() -// { -// assetsInCache = 0; -// assetCacheMemoryUsage = 0; -// texturesInCache = 0; -// textureCacheMemoryUsage = 0; -// } -// -// public void AddAssetRequestTimeAfterCacheMiss(TimeSpan ts) -// { -// assetRequestTimeAfterCacheMiss = ts; -// } -// -// public void AddBlockedMissingTextureRequest() -// { -// blockedMissingTextureRequests++; -// } -// -// public void AddAssetServiceRequestFailure() -// { -// assetServiceRequestFailures++; -// } - -// public void AddInventoryServiceRetrievalFailure() -// { -// inventoryServiceRetrievalFailures++; -// } - - /// - /// Register as a packet queue stats provider - /// - /// An agent UUID - /// - public void RegisterPacketQueueStatsProvider(UUID uuid, IPullStatsProvider provider) - { - lock (packetQueueStatsCollectors) - { - // FIXME: If the region service is providing more than one region, then the child and root agent - // queues are wrongly replacing each other here. - packetQueueStatsCollectors[uuid] = new PacketQueueStatsCollector(provider); - } - } - - /// - /// Deregister a packet queue stats provider - /// - /// An agent UUID - public void DeregisterPacketQueueStatsProvider(UUID uuid) - { - lock (packetQueueStatsCollectors) - { - packetQueueStatsCollectors.Remove(uuid); - } - } - - /// - /// This is the method on which the classic sim stats reporter (which collects stats for - /// client purposes) sends information to listeners. - /// - /// - public void ReceiveClassicSimStatsPacket(SimStats stats) - { - // FIXME: SimStats shouldn't allow an arbitrary stat packing order (which is inherited from the original - // SimStatsPacket that was being used). - timeDilation = stats.StatsBlock[0].StatValue; - simFps = stats.StatsBlock[1].StatValue; - physicsFps = stats.StatsBlock[2].StatValue; - agentUpdates = stats.StatsBlock[3].StatValue; - rootAgents = stats.StatsBlock[4].StatValue; - childAgents = stats.StatsBlock[5].StatValue; - totalPrims = stats.StatsBlock[6].StatValue; - activePrims = stats.StatsBlock[7].StatValue; - totalFrameTime = stats.StatsBlock[8].StatValue; - netFrameTime = stats.StatsBlock[9].StatValue; - physicsFrameTime = stats.StatsBlock[10].StatValue; - otherFrameTime = stats.StatsBlock[11].StatValue; - imageFrameTime = stats.StatsBlock[12].StatValue; - inPacketsPerSecond = stats.StatsBlock[13].StatValue; - outPacketsPerSecond = stats.StatsBlock[14].StatValue; - unackedBytes = stats.StatsBlock[15].StatValue; - agentFrameTime = stats.StatsBlock[16].StatValue; - pendingDownloads = stats.StatsBlock[17].StatValue; - pendingUploads = stats.StatsBlock[18].StatValue; - activeScripts = stats.StatsBlock[19].StatValue; - scriptLinesPerSecond = stats.StatsBlock[20].StatValue; - } - - /// - /// Report back collected statistical information. - /// - /// - public override string Report() - { - StringBuilder sb = new StringBuilder(Environment.NewLine); -// sb.Append("ASSET STATISTICS"); -// sb.Append(Environment.NewLine); - - /* - sb.Append( - string.Format( -@"Asset cache contains {0,6} non-texture assets using {1,10} K -Texture cache contains {2,6} texture assets using {3,10} K -Latest asset request time after cache miss: {4}s -Blocked client requests for missing textures: {5} -Asset service request failures: {6}"+ Environment.NewLine, - AssetsInCache, Math.Round(AssetCacheMemoryUsage / 1024.0), - TexturesInCache, Math.Round(TextureCacheMemoryUsage / 1024.0), - assetRequestTimeAfterCacheMiss.Milliseconds / 1000.0, - BlockedMissingTextureRequests, - AssetServiceRequestFailures)); - */ - - /* - sb.Append( - string.Format( -@"Asset cache contains {0,6} assets -Latest asset request time after cache miss: {1}s -Blocked client requests for missing textures: {2} -Asset service request failures: {3}" + Environment.NewLine, - AssetsInCache, - assetRequestTimeAfterCacheMiss.Milliseconds / 1000.0, - BlockedMissingTextureRequests, - AssetServiceRequestFailures)); - */ - - sb.Append(Environment.NewLine); - sb.Append("CONNECTION STATISTICS"); - sb.Append(Environment.NewLine); - sb.Append( - string.Format( - "Abnormal client thread terminations: {0}" + Environment.NewLine, - abnormalClientThreadTerminations)); - -// sb.Append(Environment.NewLine); -// sb.Append("INVENTORY STATISTICS"); -// sb.Append(Environment.NewLine); -// sb.Append( -// string.Format( -// "Initial inventory caching failures: {0}" + Environment.NewLine, -// InventoryServiceRetrievalFailures)); - - sb.Append(Environment.NewLine); - sb.Append("FRAME STATISTICS"); - sb.Append(Environment.NewLine); - sb.Append("Dilatn SimFPS PhyFPS AgntUp RootAg ChldAg Prims AtvPrm AtvScr ScrLPS"); - sb.Append(Environment.NewLine); - sb.Append( - string.Format( - "{0,6:0.00} {1,6:0} {2,6:0.0} {3,6:0.0} {4,6:0} {5,6:0} {6,6:0} {7,6:0} {8,6:0} {9,6:0}", - timeDilation, simFps, physicsFps, agentUpdates, rootAgents, - childAgents, totalPrims, activePrims, activeScripts, scriptLinesPerSecond)); - - sb.Append(Environment.NewLine); - sb.Append(Environment.NewLine); - // There is no script frame time currently because we don't yet collect it - sb.Append("PktsIn PktOut PendDl PendUl UnackB TotlFt NetFt PhysFt OthrFt AgntFt ImgsFt"); - sb.Append(Environment.NewLine); - sb.Append( - string.Format( - "{0,6:0} {1,6:0} {2,6:0} {3,6:0} {4,6:0} {5,6:0.0} {6,6:0.0} {7,6:0.0} {8,6:0.0} {9,6:0.0} {10,6:0.0}", - inPacketsPerSecond, outPacketsPerSecond, pendingDownloads, pendingUploads, unackedBytes, totalFrameTime, - netFrameTime, physicsFrameTime, otherFrameTime, agentFrameTime, imageFrameTime)); - sb.Append(Environment.NewLine); - - /* - sb.Append(Environment.NewLine); - sb.Append("PACKET QUEUE STATISTICS"); - sb.Append(Environment.NewLine); - sb.Append("Agent UUID "); - sb.Append( - string.Format( - " {0,7} {1,7} {2,7} {3,7} {4,7} {5,7} {6,7} {7,7} {8,7} {9,7}", - "Send", "In", "Out", "Resend", "Land", "Wind", "Cloud", "Task", "Texture", "Asset")); - sb.Append(Environment.NewLine); - - foreach (UUID key in packetQueueStatsCollectors.Keys) - { - sb.Append(string.Format("{0}: ", key)); - sb.Append(packetQueueStatsCollectors[key].Report()); - sb.Append(Environment.NewLine); - } - */ - - sb.Append(base.Report()); - - return sb.ToString(); - } - - /// - /// Report back collected statistical information as json serialization. - /// - /// - public override string XReport(string uptime, string version) - { - OSDMap args = new OSDMap(30); -// args["AssetsInCache"] = OSD.FromString (String.Format ("{0:0.##}", AssetsInCache)); -// args["TimeAfterCacheMiss"] = OSD.FromString (String.Format ("{0:0.##}", -// assetRequestTimeAfterCacheMiss.Milliseconds / 1000.0)); -// args["BlockedMissingTextureRequests"] = OSD.FromString (String.Format ("{0:0.##}", -// BlockedMissingTextureRequests)); -// args["AssetServiceRequestFailures"] = OSD.FromString (String.Format ("{0:0.##}", -// AssetServiceRequestFailures)); -// args["abnormalClientThreadTerminations"] = OSD.FromString (String.Format ("{0:0.##}", -// abnormalClientThreadTerminations)); -// args["InventoryServiceRetrievalFailures"] = OSD.FromString (String.Format ("{0:0.##}", -// InventoryServiceRetrievalFailures)); - args["Dilatn"] = OSD.FromString (String.Format ("{0:0.##}", timeDilation)); - args["SimFPS"] = OSD.FromString (String.Format ("{0:0.##}", simFps)); - args["PhyFPS"] = OSD.FromString (String.Format ("{0:0.##}", physicsFps)); - args["AgntUp"] = OSD.FromString (String.Format ("{0:0.##}", agentUpdates)); - args["RootAg"] = OSD.FromString (String.Format ("{0:0.##}", rootAgents)); - args["ChldAg"] = OSD.FromString (String.Format ("{0:0.##}", childAgents)); - args["Prims"] = OSD.FromString (String.Format ("{0:0.##}", totalPrims)); - args["AtvPrm"] = OSD.FromString (String.Format ("{0:0.##}", activePrims)); - args["AtvScr"] = OSD.FromString (String.Format ("{0:0.##}", activeScripts)); - args["ScrLPS"] = OSD.FromString (String.Format ("{0:0.##}", scriptLinesPerSecond)); - args["PktsIn"] = OSD.FromString (String.Format ("{0:0.##}", inPacketsPerSecond)); - args["PktOut"] = OSD.FromString (String.Format ("{0:0.##}", outPacketsPerSecond)); - args["PendDl"] = OSD.FromString (String.Format ("{0:0.##}", pendingDownloads)); - args["PendUl"] = OSD.FromString (String.Format ("{0:0.##}", pendingUploads)); - args["UnackB"] = OSD.FromString (String.Format ("{0:0.##}", unackedBytes)); - args["TotlFt"] = OSD.FromString (String.Format ("{0:0.##}", totalFrameTime)); - args["NetFt"] = OSD.FromString (String.Format ("{0:0.##}", netFrameTime)); - args["PhysFt"] = OSD.FromString (String.Format ("{0:0.##}", physicsFrameTime)); - args["OthrFt"] = OSD.FromString (String.Format ("{0:0.##}", otherFrameTime)); - args["AgntFt"] = OSD.FromString (String.Format ("{0:0.##}", agentFrameTime)); - args["ImgsFt"] = OSD.FromString (String.Format ("{0:0.##}", imageFrameTime)); - args["Memory"] = OSD.FromString (base.XReport (uptime, version)); - args["Uptime"] = OSD.FromString (uptime); - args["Version"] = OSD.FromString (version); - - string strBuffer = ""; - strBuffer = OSDParser.SerializeJsonString(args); - - return strBuffer; - } - } - - /// - /// Pull packet queue stats from packet queues and report - /// - public class PacketQueueStatsCollector : IStatsCollector - { - private IPullStatsProvider m_statsProvider; - - public PacketQueueStatsCollector(IPullStatsProvider provider) - { - m_statsProvider = provider; - } - - /// - /// Report back collected statistical information. - /// - /// - public string Report() - { - return m_statsProvider.GetStats(); - } - - public string XReport(string uptime, string version) - { - return ""; - } - } -} diff --git a/OpenSim/Framework/Statistics/StatsManager.cs b/OpenSim/Framework/Statistics/StatsManager.cs deleted file mode 100644 index 436ce2f..0000000 --- a/OpenSim/Framework/Statistics/StatsManager.cs +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -namespace OpenSim.Framework.Statistics -{ - /// - /// Singleton used to provide access to statistics reporters - /// - public class StatsManager - { - private static AssetStatsCollector assetStats; - private static UserStatsCollector userStats; - private static SimExtraStatsCollector simExtraStats = new SimExtraStatsCollector(); - - public static AssetStatsCollector AssetStats { get { return assetStats; } } - public static UserStatsCollector UserStats { get { return userStats; } } - public static SimExtraStatsCollector SimExtraStats { get { return simExtraStats; } } - - /// - /// Start collecting statistics related to assets. - /// Should only be called once. - /// - public static AssetStatsCollector StartCollectingAssetStats() - { - assetStats = new AssetStatsCollector(); - - return assetStats; - } - - /// - /// Start collecting statistics related to users. - /// Should only be called once. - /// - public static UserStatsCollector StartCollectingUserStats() - { - userStats = new UserStatsCollector(); - - return userStats; - } - } -} \ No newline at end of file diff --git a/OpenSim/Framework/Statistics/UserStatsCollector.cs b/OpenSim/Framework/Statistics/UserStatsCollector.cs deleted file mode 100644 index fd2a9bf..0000000 --- a/OpenSim/Framework/Statistics/UserStatsCollector.cs +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.Timers; - -namespace OpenSim.Framework.Statistics -{ - /// - /// Collects user service statistics - /// - public class UserStatsCollector : BaseStatsCollector - { - private Timer ageStatsTimer = new Timer(24 * 60 * 60 * 1000); - - private int successfulLoginsToday; - public int SuccessfulLoginsToday { get { return successfulLoginsToday; } } - - private int successfulLoginsYesterday; - public int SuccessfulLoginsYesterday { get { return successfulLoginsYesterday; } } - - private int successfulLogins; - public int SuccessfulLogins { get { return successfulLogins; } } - - private int logouts; - public int Logouts { get { return logouts; } } - - public UserStatsCollector() - { - ageStatsTimer.Elapsed += new ElapsedEventHandler(OnAgeing); - ageStatsTimer.Enabled = true; - } - - private void OnAgeing(object source, ElapsedEventArgs e) - { - successfulLoginsYesterday = successfulLoginsToday; - - // There is a possibility that an asset request could occur between the execution of these - // two statements. But we're better off without the synchronization overhead. - successfulLoginsToday = 0; - } - - /// - /// Record a successful login - /// - public void AddSuccessfulLogin() - { - successfulLogins++; - successfulLoginsToday++; - } - - public void AddLogout() - { - logouts++; - } - - /// - /// Report back collected statistical information. - /// - /// - override public string Report() - { - return string.Format( -@"Successful logins total : {0}, today : {1}, yesterday : {2} - Logouts total : {3}", - SuccessfulLogins, SuccessfulLoginsToday, SuccessfulLoginsYesterday, Logouts); - } - } -} diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs index f68974c..07a9756 100644 --- a/OpenSim/Region/Application/OpenSim.cs +++ b/OpenSim/Region/Application/OpenSim.cs @@ -40,7 +40,7 @@ using OpenMetaverse; using OpenSim.Framework; using OpenSim.Framework.Console; using OpenSim.Framework.Servers; -using OpenSim.Framework.Statistics; +using OpenSim.Framework.Monitoring; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs index 825c4c4..4084741 100644 --- a/OpenSim/Region/Application/OpenSimBase.cs +++ b/OpenSim/Region/Application/OpenSimBase.cs @@ -40,7 +40,7 @@ using OpenSim.Framework.Communications; using OpenSim.Framework.Console; using OpenSim.Framework.Servers; using OpenSim.Framework.Servers.HttpServer; -using OpenSim.Framework.Statistics; +using OpenSim.Framework.Monitoring; using OpenSim.Region.ClientStack; using OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts; using OpenSim.Region.Framework; diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index f7864b8..01ceeed 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -41,7 +41,7 @@ using OpenMetaverse.Messages.Linden; using OpenMetaverse.StructuredData; using OpenSim.Framework; using OpenSim.Framework.Client; -using OpenSim.Framework.Statistics; +using OpenSim.Framework.Monitoring; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; using OpenSim.Services.Interfaces; diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index 746eb90..55780d6 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs @@ -37,7 +37,7 @@ using log4net; using Nini.Config; using OpenMetaverse.Packets; using OpenSim.Framework; -using OpenSim.Framework.Statistics; +using OpenSim.Framework.Monitoring; using OpenSim.Region.Framework.Scenes; using OpenMetaverse; diff --git a/OpenSim/Region/CoreModules/Avatar/Commands/UserCommandsModule.cs b/OpenSim/Region/CoreModules/Avatar/Commands/UserCommandsModule.cs index 4bcd2ac..764adf9 100644 --- a/OpenSim/Region/CoreModules/Avatar/Commands/UserCommandsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Commands/UserCommandsModule.cs @@ -37,7 +37,7 @@ using Nini.Config; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Framework.Console; -using OpenSim.Framework.Statistics; +using OpenSim.Framework.Monitoring; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs index 990dffb..11e0150 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs @@ -31,7 +31,7 @@ using System.Collections.Generic; using System.Reflection; using Nini.Config; using OpenSim.Framework; -using OpenSim.Framework.Statistics; +using OpenSim.Framework.Monitoring; using OpenSim.Services.Connectors; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; diff --git a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs index e5cd3e2..09f6758 100644 --- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs +++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs @@ -37,7 +37,7 @@ using Nini.Config; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Framework.Console; -using OpenSim.Framework.Statistics; +using OpenSim.Framework.Monitoring; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; diff --git a/OpenSim/Region/CoreModules/World/Region/RegionCommandsModule.cs b/OpenSim/Region/CoreModules/World/Region/RegionCommandsModule.cs index 2838e0c..7d35473 100644 --- a/OpenSim/Region/CoreModules/World/Region/RegionCommandsModule.cs +++ b/OpenSim/Region/CoreModules/World/Region/RegionCommandsModule.cs @@ -37,7 +37,7 @@ using Nini.Config; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Framework.Console; -using OpenSim.Framework.Statistics; +using OpenSim.Framework.Monitoring; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; diff --git a/OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs b/OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs index 1365831..c11174d 100644 --- a/OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs +++ b/OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs @@ -39,7 +39,7 @@ using OpenSim.Framework.Communications; using OpenSim.Framework.Console; using OpenSim.Framework.Servers; using OpenSim.Framework.Servers.HttpServer; -using OpenSim.Framework.Statistics; +using OpenSim.Framework.Monitoring; using OpenSim.Region.Framework; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; diff --git a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs index 742d42a..96317c3 100644 --- a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs +++ b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs @@ -30,7 +30,7 @@ using System.Collections.Generic; using System.Timers; using OpenMetaverse.Packets; using OpenSim.Framework; -using OpenSim.Framework.Statistics; +using OpenSim.Framework.Monitoring; using OpenSim.Region.Framework.Interfaces; namespace OpenSim.Region.Framework.Scenes diff --git a/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs b/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs index ca9bd4a..5fe5948 100644 --- a/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs +++ b/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs @@ -35,7 +35,7 @@ using Nini.Config; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Framework.Console; -using OpenSim.Framework.Statistics; +using OpenSim.Framework.Monitoring; using OpenSim.Region.ClientStack.LindenUDP; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; diff --git a/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs b/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs index 6bb6729..d718a2f 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs @@ -36,7 +36,7 @@ using Nini.Config; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Framework.Console; -using OpenSim.Framework.Statistics; +using OpenSim.Framework.Monitoring; using OpenSim.Region.ClientStack.LindenUDP; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; diff --git a/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs b/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs index 1b9e3ac..d68aabc 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs @@ -36,7 +36,7 @@ using Nini.Config; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Framework.Console; -using OpenSim.Framework.Statistics; +using OpenSim.Framework.Monitoring; using OpenSim.Region.ClientStack.LindenUDP; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; diff --git a/OpenSim/Region/OptionalModules/Avatar/Friends/FriendsCommandsModule.cs b/OpenSim/Region/OptionalModules/Avatar/Friends/FriendsCommandsModule.cs index 2602050..4e84364 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Friends/FriendsCommandsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Friends/FriendsCommandsModule.cs @@ -37,7 +37,7 @@ using Nini.Config; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Framework.Console; -using OpenSim.Framework.Statistics; +using OpenSim.Framework.Monitoring; using OpenSim.Region.ClientStack.LindenUDP; using OpenSim.Region.CoreModules.Avatar.Friends; using OpenSim.Region.Framework.Interfaces; diff --git a/OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs b/OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs index dcbd717..3243a9a 100644 --- a/OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs +++ b/OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs @@ -34,7 +34,7 @@ using Mono.Data.SqliteClient; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Region.Framework.Scenes; -using OpenSim.Framework.Statistics; +using OpenSim.Framework.Monitoring; namespace OpenSim.Region.UserStatistics { diff --git a/OpenSim/Region/UserStatistics/Default_Report.cs b/OpenSim/Region/UserStatistics/Default_Report.cs index 0e17630..cdc615c 100644 --- a/OpenSim/Region/UserStatistics/Default_Report.cs +++ b/OpenSim/Region/UserStatistics/Default_Report.cs @@ -33,7 +33,7 @@ using System.Text; using Mono.Data.SqliteClient; using OpenMetaverse; using OpenSim.Region.Framework.Scenes; -using OpenSim.Framework.Statistics; +using OpenSim.Framework.Monitoring; namespace OpenSim.Region.UserStatistics diff --git a/OpenSim/Region/UserStatistics/LogLinesAJAX.cs b/OpenSim/Region/UserStatistics/LogLinesAJAX.cs index 811baba..74de46b 100644 --- a/OpenSim/Region/UserStatistics/LogLinesAJAX.cs +++ b/OpenSim/Region/UserStatistics/LogLinesAJAX.cs @@ -34,7 +34,7 @@ using System.Text.RegularExpressions; using Mono.Data.SqliteClient; using OpenMetaverse; using OpenSim.Region.Framework.Scenes; -using OpenSim.Framework.Statistics; +using OpenSim.Framework.Monitoring; namespace OpenSim.Region.UserStatistics { diff --git a/OpenSim/Region/UserStatistics/SimStatsAJAX.cs b/OpenSim/Region/UserStatistics/SimStatsAJAX.cs index 8c04e71..28051fb 100644 --- a/OpenSim/Region/UserStatistics/SimStatsAJAX.cs +++ b/OpenSim/Region/UserStatistics/SimStatsAJAX.cs @@ -33,7 +33,7 @@ using System.Text; using Mono.Data.SqliteClient; using OpenMetaverse; using OpenSim.Region.Framework.Scenes; -using OpenSim.Framework.Statistics; +using OpenSim.Framework.Monitoring; namespace OpenSim.Region.UserStatistics { -- cgit v1.1 From 5aec0ff207e9427b8756471eb003fd68859f67b1 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 25 Jul 2012 23:27:00 +0100 Subject: Move Watchdog and MemoryWatchdog classes into OpenSim.Framework.Monitoring with other monitoring code from OpenSim.Framework --- OpenSim/Framework/MemoryWatchdog.cs | 129 -------- OpenSim/Framework/Monitoring/MemoryWatchdog.cs | 129 ++++++++ OpenSim/Framework/Monitoring/Watchdog.cs | 334 +++++++++++++++++++++ OpenSim/Framework/Servers/BaseOpenSimServer.cs | 1 + .../Framework/Servers/HttpServer/BaseHttpServer.cs | 1 + .../HttpServer/PollServiceRequestManager.cs | 1 + .../Servers/HttpServer/PollServiceWorkerThread.cs | 1 + OpenSim/Framework/Watchdog.cs | 334 --------------------- .../InterGrid/OpenGridProtocolModule.cs | 1 + .../CoreModules/World/WorldMap/WorldMapModule.cs | 1 + OpenSim/Region/Framework/Scenes/Scene.cs | 1 + .../Server/IRCClientView.cs | 1 + .../InternetRelayClientView/Server/IRCServer.cs | 1 + .../OptionalModules/Avatar/Chat/IRCConnector.cs | 1 + .../Api/Implementation/AsyncCommandManager.cs | 1 + 15 files changed, 474 insertions(+), 463 deletions(-) delete mode 100644 OpenSim/Framework/MemoryWatchdog.cs create mode 100644 OpenSim/Framework/Monitoring/MemoryWatchdog.cs create mode 100644 OpenSim/Framework/Monitoring/Watchdog.cs delete mode 100644 OpenSim/Framework/Watchdog.cs (limited to 'OpenSim') diff --git a/OpenSim/Framework/MemoryWatchdog.cs b/OpenSim/Framework/MemoryWatchdog.cs deleted file mode 100644 index 1e93077..0000000 --- a/OpenSim/Framework/MemoryWatchdog.cs +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Threading; -using log4net; - -namespace OpenSim.Framework -{ - /// - /// Experimental watchdog for memory usage. - /// - public static class MemoryWatchdog - { -// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - /// - /// Is this watchdog active? - /// - public static bool Enabled - { - get { return m_enabled; } - set - { -// m_log.DebugFormat("[MEMORY WATCHDOG]: Setting MemoryWatchdog.Enabled to {0}", value); - - if (value && !m_enabled) - UpdateLastRecord(GC.GetTotalMemory(false), Util.EnvironmentTickCount()); - - m_enabled = value; - } - } - private static bool m_enabled; - - /// - /// Average memory churn in bytes per millisecond. - /// - public static double AverageMemoryChurn - { - get { if (m_samples.Count > 0) return m_samples.Average(); else return 0; } - } - - /// - /// Maximum number of statistical samples. - /// - /// - /// At the moment this corresponds to 1 minute since the sampling rate is every 2.5 seconds as triggered from - /// the main Watchdog. - /// - private static int m_maxSamples = 24; - - /// - /// Time when the watchdog was last updated. - /// - private static int m_lastUpdateTick; - - /// - /// Memory used at time of last watchdog update. - /// - private static long m_lastUpdateMemory; - - /// - /// Memory churn rate per millisecond. - /// - private static double m_churnRatePerMillisecond; - - /// - /// Historical samples for calculating moving average. - /// - private static Queue m_samples = new Queue(m_maxSamples); - - public static void Update() - { - int now = Util.EnvironmentTickCount(); - long memoryNow = GC.GetTotalMemory(false); - long memoryDiff = memoryNow - m_lastUpdateMemory; - - if (memoryDiff >= 0) - { - if (m_samples.Count >= m_maxSamples) - m_samples.Dequeue(); - - double elapsed = Util.EnvironmentTickCountSubtract(now, m_lastUpdateTick); - - // This should never happen since it's not useful for updates to occur with no time elapsed, but - // protect ourselves from a divide-by-zero just in case. - if (elapsed == 0) - return; - - m_samples.Enqueue(memoryDiff / (double)elapsed); - } - - UpdateLastRecord(memoryNow, now); - } - - private static void UpdateLastRecord(long memoryNow, int timeNow) - { - m_lastUpdateMemory = memoryNow; - m_lastUpdateTick = timeNow; - } - } -} \ No newline at end of file diff --git a/OpenSim/Framework/Monitoring/MemoryWatchdog.cs b/OpenSim/Framework/Monitoring/MemoryWatchdog.cs new file mode 100644 index 0000000..6599613 --- /dev/null +++ b/OpenSim/Framework/Monitoring/MemoryWatchdog.cs @@ -0,0 +1,129 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Threading; +using log4net; + +namespace OpenSim.Framework.Monitoring +{ + /// + /// Experimental watchdog for memory usage. + /// + public static class MemoryWatchdog + { +// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// Is this watchdog active? + /// + public static bool Enabled + { + get { return m_enabled; } + set + { +// m_log.DebugFormat("[MEMORY WATCHDOG]: Setting MemoryWatchdog.Enabled to {0}", value); + + if (value && !m_enabled) + UpdateLastRecord(GC.GetTotalMemory(false), Util.EnvironmentTickCount()); + + m_enabled = value; + } + } + private static bool m_enabled; + + /// + /// Average memory churn in bytes per millisecond. + /// + public static double AverageMemoryChurn + { + get { if (m_samples.Count > 0) return m_samples.Average(); else return 0; } + } + + /// + /// Maximum number of statistical samples. + /// + /// + /// At the moment this corresponds to 1 minute since the sampling rate is every 2.5 seconds as triggered from + /// the main Watchdog. + /// + private static int m_maxSamples = 24; + + /// + /// Time when the watchdog was last updated. + /// + private static int m_lastUpdateTick; + + /// + /// Memory used at time of last watchdog update. + /// + private static long m_lastUpdateMemory; + + /// + /// Memory churn rate per millisecond. + /// + private static double m_churnRatePerMillisecond; + + /// + /// Historical samples for calculating moving average. + /// + private static Queue m_samples = new Queue(m_maxSamples); + + public static void Update() + { + int now = Util.EnvironmentTickCount(); + long memoryNow = GC.GetTotalMemory(false); + long memoryDiff = memoryNow - m_lastUpdateMemory; + + if (memoryDiff >= 0) + { + if (m_samples.Count >= m_maxSamples) + m_samples.Dequeue(); + + double elapsed = Util.EnvironmentTickCountSubtract(now, m_lastUpdateTick); + + // This should never happen since it's not useful for updates to occur with no time elapsed, but + // protect ourselves from a divide-by-zero just in case. + if (elapsed == 0) + return; + + m_samples.Enqueue(memoryDiff / (double)elapsed); + } + + UpdateLastRecord(memoryNow, now); + } + + private static void UpdateLastRecord(long memoryNow, int timeNow) + { + m_lastUpdateMemory = memoryNow; + m_lastUpdateTick = timeNow; + } + } +} \ No newline at end of file diff --git a/OpenSim/Framework/Monitoring/Watchdog.cs b/OpenSim/Framework/Monitoring/Watchdog.cs new file mode 100644 index 0000000..d4cf02f --- /dev/null +++ b/OpenSim/Framework/Monitoring/Watchdog.cs @@ -0,0 +1,334 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using log4net; + +namespace OpenSim.Framework.Monitoring +{ + /// + /// Manages launching threads and keeping watch over them for timeouts + /// + public static class Watchdog + { + /// Timer interval in milliseconds for the watchdog timer + const double WATCHDOG_INTERVAL_MS = 2500.0d; + + /// Default timeout in milliseconds before a thread is considered dead + public const int DEFAULT_WATCHDOG_TIMEOUT_MS = 5000; + + [System.Diagnostics.DebuggerDisplay("{Thread.Name}")] + public class ThreadWatchdogInfo + { + public Thread Thread { get; private set; } + + /// + /// Approximate tick when this thread was started. + /// + /// + /// Not terribly good since this quickly wraps around. + /// + public int FirstTick { get; private set; } + + /// + /// Last time this heartbeat update was invoked + /// + public int LastTick { get; set; } + + /// + /// Number of milliseconds before we notify that the thread is having a problem. + /// + public int Timeout { get; set; } + + /// + /// Is this thread considered timed out? + /// + public bool IsTimedOut { get; set; } + + /// + /// Will this thread trigger the alarm function if it has timed out? + /// + public bool AlarmIfTimeout { get; set; } + + /// + /// Method execute if alarm goes off. If null then no alarm method is fired. + /// + public Func AlarmMethod { get; set; } + + public ThreadWatchdogInfo(Thread thread, int timeout) + { + Thread = thread; + Timeout = timeout; + FirstTick = Environment.TickCount & Int32.MaxValue; + LastTick = FirstTick; + } + } + + /// + /// This event is called whenever a tracked thread is + /// stopped or has not called UpdateThread() in time< + /// /summary> + public static event Action OnWatchdogTimeout; + + private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + private static Dictionary m_threads; + private static System.Timers.Timer m_watchdogTimer; + + /// + /// Last time the watchdog thread ran. + /// + /// + /// Should run every WATCHDOG_INTERVAL_MS + /// + public static int LastWatchdogThreadTick { get; private set; } + + static Watchdog() + { + m_threads = new Dictionary(); + m_watchdogTimer = new System.Timers.Timer(WATCHDOG_INTERVAL_MS); + m_watchdogTimer.AutoReset = false; + m_watchdogTimer.Elapsed += WatchdogTimerElapsed; + + // Set now so we don't get alerted on the first run + LastWatchdogThreadTick = Environment.TickCount & Int32.MaxValue; + + m_watchdogTimer.Start(); + } + + /// + /// Start a new thread that is tracked by the watchdog timer. + /// + /// The method that will be executed in a new thread + /// A name to give to the new thread + /// Priority to run the thread at + /// True to run this thread as a background thread, otherwise false + /// Trigger an alarm function is we have timed out + /// The newly created Thread object + public static Thread StartThread( + ThreadStart start, string name, ThreadPriority priority, bool isBackground, bool alarmIfTimeout) + { + return StartThread(start, name, priority, isBackground, alarmIfTimeout, null, DEFAULT_WATCHDOG_TIMEOUT_MS); + } + + /// + /// Start a new thread that is tracked by the watchdog timer + /// + /// The method that will be executed in a new thread + /// A name to give to the new thread + /// Priority to run the thread at + /// True to run this thread as a background + /// thread, otherwise false + /// Trigger an alarm function is we have timed out + /// + /// Alarm method to call if alarmIfTimeout is true and there is a timeout. + /// Normally, this will just return some useful debugging information. + /// + /// Number of milliseconds to wait until we issue a warning about timeout. + /// The newly created Thread object + public static Thread StartThread( + ThreadStart start, string name, ThreadPriority priority, bool isBackground, + bool alarmIfTimeout, Func alarmMethod, int timeout) + { + Thread thread = new Thread(start); + thread.Name = name; + thread.Priority = priority; + thread.IsBackground = isBackground; + + ThreadWatchdogInfo twi + = new ThreadWatchdogInfo(thread, timeout) + { AlarmIfTimeout = alarmIfTimeout, AlarmMethod = alarmMethod }; + + m_log.DebugFormat( + "[WATCHDOG]: Started tracking thread {0}, ID {1}", twi.Thread.Name, twi.Thread.ManagedThreadId); + + lock (m_threads) + m_threads.Add(twi.Thread.ManagedThreadId, twi); + + thread.Start(); + + return thread; + } + + /// + /// Marks the current thread as alive + /// + public static void UpdateThread() + { + UpdateThread(Thread.CurrentThread.ManagedThreadId); + } + + /// + /// Stops watchdog tracking on the current thread + /// + /// + /// True if the thread was removed from the list of tracked + /// threads, otherwise false + /// + public static bool RemoveThread() + { + return RemoveThread(Thread.CurrentThread.ManagedThreadId); + } + + private static bool RemoveThread(int threadID) + { + lock (m_threads) + return m_threads.Remove(threadID); + } + + public static bool AbortThread(int threadID) + { + lock (m_threads) + { + if (m_threads.ContainsKey(threadID)) + { + ThreadWatchdogInfo twi = m_threads[threadID]; + twi.Thread.Abort(); + RemoveThread(threadID); + + return true; + } + else + { + return false; + } + } + } + + private static void UpdateThread(int threadID) + { + ThreadWatchdogInfo threadInfo; + + // Although TryGetValue is not a thread safe operation, we use a try/catch here instead + // of a lock for speed. Adding/removing threads is a very rare operation compared to + // UpdateThread(), and a single UpdateThread() failure here and there won't break + // anything + try + { + if (m_threads.TryGetValue(threadID, out threadInfo)) + { + threadInfo.LastTick = Environment.TickCount & Int32.MaxValue; + threadInfo.IsTimedOut = false; + } + else + { + m_log.WarnFormat("[WATCHDOG]: Asked to update thread {0} which is not being monitored", threadID); + } + } + catch { } + } + + /// + /// Get currently watched threads for diagnostic purposes + /// + /// + public static ThreadWatchdogInfo[] GetThreadsInfo() + { + lock (m_threads) + return m_threads.Values.ToArray(); + } + + /// + /// Return the current thread's watchdog info. + /// + /// The watchdog info. null if the thread isn't being monitored. + public static ThreadWatchdogInfo GetCurrentThreadInfo() + { + lock (m_threads) + { + if (m_threads.ContainsKey(Thread.CurrentThread.ManagedThreadId)) + return m_threads[Thread.CurrentThread.ManagedThreadId]; + } + + return null; + } + + /// + /// Check watched threads. Fire alarm if appropriate. + /// + /// + /// + private static void WatchdogTimerElapsed(object sender, System.Timers.ElapsedEventArgs e) + { + int now = Environment.TickCount & Int32.MaxValue; + int msElapsed = now - LastWatchdogThreadTick; + + if (msElapsed > WATCHDOG_INTERVAL_MS * 2) + m_log.WarnFormat( + "[WATCHDOG]: {0} ms since Watchdog last ran. Interval should be approximately {1} ms", + msElapsed, WATCHDOG_INTERVAL_MS); + + LastWatchdogThreadTick = Environment.TickCount & Int32.MaxValue; + + Action callback = OnWatchdogTimeout; + + if (callback != null) + { + List callbackInfos = null; + + lock (m_threads) + { + foreach (ThreadWatchdogInfo threadInfo in m_threads.Values) + { + if (threadInfo.Thread.ThreadState == ThreadState.Stopped) + { + RemoveThread(threadInfo.Thread.ManagedThreadId); + + if (callbackInfos == null) + callbackInfos = new List(); + + callbackInfos.Add(threadInfo); + } + else if (!threadInfo.IsTimedOut && now - threadInfo.LastTick >= threadInfo.Timeout) + { + threadInfo.IsTimedOut = true; + + if (threadInfo.AlarmIfTimeout) + { + if (callbackInfos == null) + callbackInfos = new List(); + + callbackInfos.Add(threadInfo); + } + } + } + } + + if (callbackInfos != null) + foreach (ThreadWatchdogInfo callbackInfo in callbackInfos) + callback(callbackInfo); + } + + if (MemoryWatchdog.Enabled) + MemoryWatchdog.Update(); + + m_watchdogTimer.Start(); + } + } +} \ No newline at end of file diff --git a/OpenSim/Framework/Servers/BaseOpenSimServer.cs b/OpenSim/Framework/Servers/BaseOpenSimServer.cs index ab8d95a..2a8ae38 100644 --- a/OpenSim/Framework/Servers/BaseOpenSimServer.cs +++ b/OpenSim/Framework/Servers/BaseOpenSimServer.cs @@ -40,6 +40,7 @@ using log4net.Core; using log4net.Repository; using OpenSim.Framework; using OpenSim.Framework.Console; +using OpenSim.Framework.Monitoring; using OpenSim.Framework.Servers; using OpenSim.Framework.Servers.HttpServer; using OpenSim.Framework.Monitoring; diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs index 3de7f9c..f57ea76 100644 --- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs +++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs @@ -45,6 +45,7 @@ using OpenMetaverse.StructuredData; using CoolHTTPListener = HttpServer.HttpListener; using HttpListener=System.Net.HttpListener; using LogPrio=HttpServer.LogPrio; +using OpenSim.Framework.Monitoring; namespace OpenSim.Framework.Servers.HttpServer { diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs index 3252251..8d50151 100644 --- a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs +++ b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs @@ -32,6 +32,7 @@ using System.Reflection; using log4net; using HttpServer; using OpenSim.Framework; +using OpenSim.Framework.Monitoring; namespace OpenSim.Framework.Servers.HttpServer { diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceWorkerThread.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceWorkerThread.cs index 35a8dee..5adbcd1 100644 --- a/OpenSim/Framework/Servers/HttpServer/PollServiceWorkerThread.cs +++ b/OpenSim/Framework/Servers/HttpServer/PollServiceWorkerThread.cs @@ -34,6 +34,7 @@ using HttpServer; using OpenMetaverse; using System.Reflection; using log4net; +using OpenSim.Framework.Monitoring; namespace OpenSim.Framework.Servers.HttpServer { diff --git a/OpenSim/Framework/Watchdog.cs b/OpenSim/Framework/Watchdog.cs deleted file mode 100644 index 54e3d1a..0000000 --- a/OpenSim/Framework/Watchdog.cs +++ /dev/null @@ -1,334 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using log4net; - -namespace OpenSim.Framework -{ - /// - /// Manages launching threads and keeping watch over them for timeouts - /// - public static class Watchdog - { - /// Timer interval in milliseconds for the watchdog timer - const double WATCHDOG_INTERVAL_MS = 2500.0d; - - /// Default timeout in milliseconds before a thread is considered dead - public const int DEFAULT_WATCHDOG_TIMEOUT_MS = 5000; - - [System.Diagnostics.DebuggerDisplay("{Thread.Name}")] - public class ThreadWatchdogInfo - { - public Thread Thread { get; private set; } - - /// - /// Approximate tick when this thread was started. - /// - /// - /// Not terribly good since this quickly wraps around. - /// - public int FirstTick { get; private set; } - - /// - /// Last time this heartbeat update was invoked - /// - public int LastTick { get; set; } - - /// - /// Number of milliseconds before we notify that the thread is having a problem. - /// - public int Timeout { get; set; } - - /// - /// Is this thread considered timed out? - /// - public bool IsTimedOut { get; set; } - - /// - /// Will this thread trigger the alarm function if it has timed out? - /// - public bool AlarmIfTimeout { get; set; } - - /// - /// Method execute if alarm goes off. If null then no alarm method is fired. - /// - public Func AlarmMethod { get; set; } - - public ThreadWatchdogInfo(Thread thread, int timeout) - { - Thread = thread; - Timeout = timeout; - FirstTick = Environment.TickCount & Int32.MaxValue; - LastTick = FirstTick; - } - } - - /// - /// This event is called whenever a tracked thread is - /// stopped or has not called UpdateThread() in time< - /// /summary> - public static event Action OnWatchdogTimeout; - - private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - private static Dictionary m_threads; - private static System.Timers.Timer m_watchdogTimer; - - /// - /// Last time the watchdog thread ran. - /// - /// - /// Should run every WATCHDOG_INTERVAL_MS - /// - public static int LastWatchdogThreadTick { get; private set; } - - static Watchdog() - { - m_threads = new Dictionary(); - m_watchdogTimer = new System.Timers.Timer(WATCHDOG_INTERVAL_MS); - m_watchdogTimer.AutoReset = false; - m_watchdogTimer.Elapsed += WatchdogTimerElapsed; - - // Set now so we don't get alerted on the first run - LastWatchdogThreadTick = Environment.TickCount & Int32.MaxValue; - - m_watchdogTimer.Start(); - } - - /// - /// Start a new thread that is tracked by the watchdog timer. - /// - /// The method that will be executed in a new thread - /// A name to give to the new thread - /// Priority to run the thread at - /// True to run this thread as a background thread, otherwise false - /// Trigger an alarm function is we have timed out - /// The newly created Thread object - public static Thread StartThread( - ThreadStart start, string name, ThreadPriority priority, bool isBackground, bool alarmIfTimeout) - { - return StartThread(start, name, priority, isBackground, alarmIfTimeout, null, DEFAULT_WATCHDOG_TIMEOUT_MS); - } - - /// - /// Start a new thread that is tracked by the watchdog timer - /// - /// The method that will be executed in a new thread - /// A name to give to the new thread - /// Priority to run the thread at - /// True to run this thread as a background - /// thread, otherwise false - /// Trigger an alarm function is we have timed out - /// - /// Alarm method to call if alarmIfTimeout is true and there is a timeout. - /// Normally, this will just return some useful debugging information. - /// - /// Number of milliseconds to wait until we issue a warning about timeout. - /// The newly created Thread object - public static Thread StartThread( - ThreadStart start, string name, ThreadPriority priority, bool isBackground, - bool alarmIfTimeout, Func alarmMethod, int timeout) - { - Thread thread = new Thread(start); - thread.Name = name; - thread.Priority = priority; - thread.IsBackground = isBackground; - - ThreadWatchdogInfo twi - = new ThreadWatchdogInfo(thread, timeout) - { AlarmIfTimeout = alarmIfTimeout, AlarmMethod = alarmMethod }; - - m_log.DebugFormat( - "[WATCHDOG]: Started tracking thread {0}, ID {1}", twi.Thread.Name, twi.Thread.ManagedThreadId); - - lock (m_threads) - m_threads.Add(twi.Thread.ManagedThreadId, twi); - - thread.Start(); - - return thread; - } - - /// - /// Marks the current thread as alive - /// - public static void UpdateThread() - { - UpdateThread(Thread.CurrentThread.ManagedThreadId); - } - - /// - /// Stops watchdog tracking on the current thread - /// - /// - /// True if the thread was removed from the list of tracked - /// threads, otherwise false - /// - public static bool RemoveThread() - { - return RemoveThread(Thread.CurrentThread.ManagedThreadId); - } - - private static bool RemoveThread(int threadID) - { - lock (m_threads) - return m_threads.Remove(threadID); - } - - public static bool AbortThread(int threadID) - { - lock (m_threads) - { - if (m_threads.ContainsKey(threadID)) - { - ThreadWatchdogInfo twi = m_threads[threadID]; - twi.Thread.Abort(); - RemoveThread(threadID); - - return true; - } - else - { - return false; - } - } - } - - private static void UpdateThread(int threadID) - { - ThreadWatchdogInfo threadInfo; - - // Although TryGetValue is not a thread safe operation, we use a try/catch here instead - // of a lock for speed. Adding/removing threads is a very rare operation compared to - // UpdateThread(), and a single UpdateThread() failure here and there won't break - // anything - try - { - if (m_threads.TryGetValue(threadID, out threadInfo)) - { - threadInfo.LastTick = Environment.TickCount & Int32.MaxValue; - threadInfo.IsTimedOut = false; - } - else - { - m_log.WarnFormat("[WATCHDOG]: Asked to update thread {0} which is not being monitored", threadID); - } - } - catch { } - } - - /// - /// Get currently watched threads for diagnostic purposes - /// - /// - public static ThreadWatchdogInfo[] GetThreadsInfo() - { - lock (m_threads) - return m_threads.Values.ToArray(); - } - - /// - /// Return the current thread's watchdog info. - /// - /// The watchdog info. null if the thread isn't being monitored. - public static ThreadWatchdogInfo GetCurrentThreadInfo() - { - lock (m_threads) - { - if (m_threads.ContainsKey(Thread.CurrentThread.ManagedThreadId)) - return m_threads[Thread.CurrentThread.ManagedThreadId]; - } - - return null; - } - - /// - /// Check watched threads. Fire alarm if appropriate. - /// - /// - /// - private static void WatchdogTimerElapsed(object sender, System.Timers.ElapsedEventArgs e) - { - int now = Environment.TickCount & Int32.MaxValue; - int msElapsed = now - LastWatchdogThreadTick; - - if (msElapsed > WATCHDOG_INTERVAL_MS * 2) - m_log.WarnFormat( - "[WATCHDOG]: {0} ms since Watchdog last ran. Interval should be approximately {1} ms", - msElapsed, WATCHDOG_INTERVAL_MS); - - LastWatchdogThreadTick = Environment.TickCount & Int32.MaxValue; - - Action callback = OnWatchdogTimeout; - - if (callback != null) - { - List callbackInfos = null; - - lock (m_threads) - { - foreach (ThreadWatchdogInfo threadInfo in m_threads.Values) - { - if (threadInfo.Thread.ThreadState == ThreadState.Stopped) - { - RemoveThread(threadInfo.Thread.ManagedThreadId); - - if (callbackInfos == null) - callbackInfos = new List(); - - callbackInfos.Add(threadInfo); - } - else if (!threadInfo.IsTimedOut && now - threadInfo.LastTick >= threadInfo.Timeout) - { - threadInfo.IsTimedOut = true; - - if (threadInfo.AlarmIfTimeout) - { - if (callbackInfos == null) - callbackInfos = new List(); - - callbackInfos.Add(threadInfo); - } - } - } - } - - if (callbackInfos != null) - foreach (ThreadWatchdogInfo callbackInfo in callbackInfos) - callback(callbackInfo); - } - - if (MemoryWatchdog.Enabled) - MemoryWatchdog.Update(); - - m_watchdogTimer.Start(); - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs b/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs index a6e2548..4a76b00 100644 --- a/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs +++ b/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs @@ -40,6 +40,7 @@ using OpenMetaverse; using OpenMetaverse.StructuredData; using OpenSim.Framework; using OpenSim.Framework.Capabilities; +using OpenSim.Framework.Monitoring; using OpenSim.Framework.Servers; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs index 724533b..dfba3ff 100644 --- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs +++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs @@ -42,6 +42,7 @@ using OpenMetaverse.Imaging; using OpenMetaverse.StructuredData; using OpenSim.Framework; using OpenSim.Framework.Capabilities; +using OpenSim.Framework.Monitoring; using OpenSim.Framework.Servers; using OpenSim.Framework.Servers.HttpServer; using OpenSim.Region.Framework.Interfaces; diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 20918bd..24f62e3 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -40,6 +40,7 @@ using OpenMetaverse; using OpenMetaverse.Packets; using OpenMetaverse.Imaging; using OpenSim.Framework; +using OpenSim.Framework.Monitoring; using OpenSim.Services.Interfaces; using OpenSim.Framework.Communications; using OpenSim.Framework.Console; diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs index 5043208..bae25cd 100644 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs @@ -38,6 +38,7 @@ using OpenMetaverse; using OpenMetaverse.Packets; using OpenSim.Framework; using OpenSim.Framework.Client; +using OpenSim.Framework.Monitoring; using OpenSim.Region.Framework.Scenes; namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCServer.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCServer.cs index a7c5020..9d27386 100644 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCServer.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCServer.cs @@ -34,6 +34,7 @@ using System.Text; using System.Threading; using log4net; using OpenSim.Framework; +using OpenSim.Framework.Monitoring; using OpenSim.Region.Framework.Scenes; namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server diff --git a/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs b/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs index cd401a6..ca956fb 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs @@ -37,6 +37,7 @@ using OpenMetaverse; using log4net; using Nini.Config; using OpenSim.Framework; +using OpenSim.Framework.Monitoring; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs index 5b22860..47a9cdc 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs @@ -31,6 +31,7 @@ using System.Collections.Generic; using System.Threading; using OpenMetaverse; using OpenSim.Framework; +using OpenSim.Framework.Monitoring; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.ScriptEngine.Interfaces; using OpenSim.Region.ScriptEngine.Shared; -- cgit v1.1 From 5707e171f4c231b58ff683d49fee55e4ccbb317f Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 25 Jul 2012 10:33:36 -0700 Subject: BulletSim: Move constraint tracking from C++ code to C# code for more flexibility. --- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 53 +++++++++++++++------- .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 48 +++++++++++++++++++- 2 files changed, 83 insertions(+), 18 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index a19d6d7..ff87955 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -97,6 +97,9 @@ public sealed class BSPrim : PhysicsActor long _collidingStep; long _collidingGroundStep; + private BulletBody m_body; + public BulletBody Body { get { return m_body; } } + private BSDynamics _vehicle; private OMV.Vector3 _PIDTarget; @@ -138,6 +141,11 @@ public sealed class BSPrim : PhysicsActor _scene.TaintedObject(delegate() { RecreateGeomAndObject(); + + // Get the pointer to the physical body for this object. + // At the moment, we're still letting BulletSim manage the creation and destruction + // of the object. Someday we'll move that into the C# code. + m_body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID)); }); } @@ -161,7 +169,7 @@ public sealed class BSPrim : PhysicsActor _parentPrim = null; } - // make sure there are no possible children depending on me + // make sure there are no other prims are linked to me UnlinkAllChildren(); // everything in the C# world will get garbage collected. Tell the C++ world to free stuff. @@ -333,11 +341,11 @@ public sealed class BSPrim : PhysicsActor _rotationalVelocity = OMV.Vector3.Zero; // Zero some other properties directly into the physics engine - IntPtr obj = BulletSimAPI.GetBodyHandleWorldID2(_scene.WorldID, LocalID); - BulletSimAPI.SetVelocity2(obj, OMV.Vector3.Zero); - BulletSimAPI.SetAngularVelocity2(obj, OMV.Vector3.Zero); - BulletSimAPI.SetInterpolation2(obj, OMV.Vector3.Zero, OMV.Vector3.Zero); - BulletSimAPI.ClearForces2(obj); + BulletBody obj = new BulletBody(LocalID, BulletSimAPI.GetBodyHandleWorldID2(_scene.WorldID, LocalID)); + BulletSimAPI.SetVelocity2(obj.Ptr, OMV.Vector3.Zero); + BulletSimAPI.SetAngularVelocity2(obj.Ptr, OMV.Vector3.Zero); + BulletSimAPI.SetInterpolation2(obj.Ptr, OMV.Vector3.Zero, OMV.Vector3.Zero); + BulletSimAPI.ClearForces2(obj.Ptr); } public override void LockAngularMotion(OMV.Vector3 axis) @@ -383,7 +391,8 @@ public sealed class BSPrim : PhysicsActor _scene.TaintedObject(delegate() { DetailLog("{0},SetForce,taint,force={1}", LocalID, _force); - BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force); + // BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force); + BulletSimAPI.SetObjectForce2(Body.Ptr, _force); }); } } @@ -407,8 +416,7 @@ public sealed class BSPrim : PhysicsActor _scene.TaintedObject(delegate() { // Tell the physics engine to clear state - IntPtr obj = BulletSimAPI.GetBodyHandleWorldID2(_scene.WorldID, LocalID); - BulletSimAPI.ClearForces2(obj); + BulletSimAPI.ClearForces2(this.Body.Ptr); }); // make it so the scene will call us each tick to do vehicle things @@ -420,7 +428,6 @@ public sealed class BSPrim : PhysicsActor } public override void VehicleFloatParam(int param, float value) { - m_log.DebugFormat("{0} VehicleFloatParam. {1} <= {2}", LogHeader, param, value); _scene.TaintedObject(delegate() { _vehicle.ProcessFloatVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep); @@ -428,7 +435,6 @@ public sealed class BSPrim : PhysicsActor } public override void VehicleVectorParam(int param, OMV.Vector3 value) { - m_log.DebugFormat("{0} VehicleVectorParam. {1} <= {2}", LogHeader, param, value); _scene.TaintedObject(delegate() { _vehicle.ProcessVectorVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep); @@ -436,7 +442,6 @@ public sealed class BSPrim : PhysicsActor } public override void VehicleRotationParam(int param, OMV.Quaternion rotation) { - m_log.DebugFormat("{0} VehicleRotationParam. {1} <= {2}", LogHeader, param, rotation); _scene.TaintedObject(delegate() { _vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation); @@ -444,7 +449,6 @@ public sealed class BSPrim : PhysicsActor } public override void VehicleFlags(int param, bool remove) { - m_log.DebugFormat("{0} VehicleFlags. {1}. Remove={2}", LogHeader, param, remove); _scene.TaintedObject(delegate() { _vehicle.ProcessVehicleFlags(param, remove); @@ -1296,7 +1300,7 @@ public sealed class BSPrim : PhysicsActor // remove any constraints that might be in place DebugLog("{0}: CreateLinkset: RemoveConstraints between me and any children", LogHeader, LocalID); - BulletSimAPI.RemoveConstraintByID(_scene.WorldID, LocalID); + UnlinkAllChildren(); // create constraints between the root prim and each of the children foreach (BSPrim prim in _childrenPrims) @@ -1323,6 +1327,7 @@ public sealed class BSPrim : PhysicsActor // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 DebugLog("{0}: CreateLinkset: Adding a constraint between root prim {1} and child prim {2}", LogHeader, LocalID, childPrim.LocalID); DetailLog("{0},LinkAChildToMe,taint,root={1},child={2}", LocalID, LocalID, childPrim.LocalID); + /* BulletSimAPI.AddConstraint(_scene.WorldID, LocalID, childPrim.LocalID, childRelativePosition, childRelativeRotation, @@ -1330,6 +1335,20 @@ public sealed class BSPrim : PhysicsActor OMV.Quaternion.Identity, OMV.Vector3.Zero, OMV.Vector3.Zero, OMV.Vector3.Zero, OMV.Vector3.Zero); + */ + // BSConstraint constrain = new BSConstraint(_scene.World, this.Body, childPrim.Body, + BSConstraint constrain = _scene.Constraints.CreateConstraint( + _scene.World, this.Body, childPrim.Body, + childRelativePosition, + childRelativeRotation, + OMV.Vector3.Zero, + OMV.Quaternion.Identity); + constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); + constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); + + // tweek the constraint to increase stability + constrain.UseFrameOffset(true); + constrain.TranslationalLimitMotor(true, 5f, 0.1f); } // Remove linkage between myself and a particular child @@ -1339,7 +1358,8 @@ public sealed class BSPrim : PhysicsActor DebugLog("{0}: UnlinkAChildFromMe: RemoveConstraint between root prim {1} and child prim {2}", LogHeader, LocalID, childPrim.LocalID); DetailLog("{0},UnlinkAChildFromMe,taint,root={1},child={2}", LocalID, LocalID, childPrim.LocalID); - BulletSimAPI.RemoveConstraint(_scene.WorldID, LocalID, childPrim.LocalID); + // BulletSimAPI.RemoveConstraint(_scene.WorldID, LocalID, childPrim.LocalID); + _scene.Constraints.RemoveAndDestroyConstraint(this.Body, childPrim.Body); } // Remove linkage between myself and any possible children I might have @@ -1348,7 +1368,8 @@ public sealed class BSPrim : PhysicsActor { DebugLog("{0}: UnlinkAllChildren:", LogHeader); DetailLog("{0},UnlinkAllChildren,taint", LocalID); - BulletSimAPI.RemoveConstraintByID(_scene.WorldID, LocalID); + _scene.Constraints.RemoveAndDestroyConstraint(this.Body); + // BulletSimAPI.RemoveConstraintByID(_scene.WorldID, LocalID); } #endregion // Linkset creation and destruction diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 54a8cfd..89fd9b7 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -32,6 +32,28 @@ using OpenMetaverse; namespace OpenSim.Region.Physics.BulletSPlugin { +// Classes to allow some type checking for the API +public struct BulletSim +{ + public BulletSim(uint id, IntPtr xx) { ID = id; Ptr = xx; } + public IntPtr Ptr; + public uint ID; +} + +public struct BulletBody +{ + public BulletBody(uint id, IntPtr xx) { ID = id; Ptr = xx; } + public IntPtr Ptr; + public uint ID; +} + +public struct BulletConstraint +{ + public BulletConstraint(IntPtr xx) { Ptr = xx; } + public IntPtr Ptr; +} + +// =============================================================================== [StructLayout(LayoutKind.Sequential)] public struct ConvexHull { @@ -142,6 +164,11 @@ public struct ConfigurationParameters public float shouldEnableFrictionCaching; public float numberOfSolverIterations; + public float linkConstraintUseFrameOffset; + public float linkConstraintEnableTransMotor; + public float linkConstraintTransMotorMaxVel; + public float linkConstraintTransMotorMaxForce; + public const float numericTrue = 1f; public const float numericFalse = 0f; } @@ -162,6 +189,7 @@ public enum CollisionFlags : uint PHYSICAL_OBJECT = 1 << 12, }; +// =============================================================================== static class BulletSimAPI { [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] @@ -214,6 +242,7 @@ public static extern bool CreateObject(uint worldID, ShapeData shapeData); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern void CreateLinkset(uint worldID, int objectCount, ShapeData[] shapeDatas); +/* Remove old functionality [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern void AddConstraint(uint worldID, uint id1, uint id2, Vector3 frame1, Quaternion frame1rot, @@ -225,6 +254,7 @@ public static extern bool RemoveConstraintByID(uint worldID, uint id1); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern bool RemoveConstraint(uint worldID, uint id1, uint id2); + */ [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern Vector3 GetObjectPosition(uint WorldID, uint id); @@ -350,8 +380,22 @@ public static extern IntPtr CreateObject2(IntPtr sim, ShapeData shapeData); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern IntPtr CreateConstraint2(IntPtr sim, IntPtr obj1, IntPtr obj2, Vector3 frame1loc, Quaternion frame1rot, - Vector3 frame2loc, Quaternion frame2rot, - Vector3 lowLinear, Vector3 hiLinear, Vector3 lowAngular, Vector3 hiAngular); + Vector3 frame2loc, Quaternion frame2rot); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool SetLinearLimits2(IntPtr constrain, Vector3 low, Vector3 hi); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool SetAngularLimits2(IntPtr constrain, Vector3 low, Vector3 hi); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool UseFrameOffset2(IntPtr constrain, float enable); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool TranslationalLimitMotor2(IntPtr constrain, float enable, float targetVel, float maxMotorForce); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool CalculateTransforms2(IntPtr constrain); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern bool DestroyConstraint2(IntPtr sim, IntPtr constrain); -- cgit v1.1 From 2d05e16f7e934fc7a986696605950dd9a618d044 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 25 Jul 2012 10:34:51 -0700 Subject: BulletSim: Add C# classes for storing and tracking constraints. --- .../Region/Physics/BulletSPlugin/BSConstraint.cs | 123 ++++++++++++++ .../BulletSPlugin/BSConstraintCollection.cs | 178 +++++++++++++++++++++ 2 files changed, 301 insertions(+) create mode 100755 OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs create mode 100755 OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs (limited to 'OpenSim') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs new file mode 100755 index 0000000..ced8565 --- /dev/null +++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs @@ -0,0 +1,123 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyrightD + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +using System; +using System.Collections.Generic; +using System.Text; +using OpenMetaverse; + +namespace OpenSim.Region.Physics.BulletSPlugin +{ + +public class BSConstraint : IDisposable +{ + private BulletSim m_world; + private BulletBody m_body1; + private BulletBody m_body2; + private BulletConstraint m_constraint; + private bool m_enabled = false; + + public BSConstraint(BulletSim world, BulletBody obj1, BulletBody obj2, + Vector3 frame1, Quaternion frame1rot, + Vector3 frame2, Quaternion frame2rot + ) + { + m_world = world; + m_body1 = obj1; + m_body2 = obj2; + /* + BulletSimAPI.AddConstraint(world.ID, m_body1.ID, m_body2.ID, + frame1, frame1rot, + frame2, frame2rot, + linearLow, linearHigh, + angularLow, angularHigh + ); + */ + m_constraint = new BulletConstraint(BulletSimAPI.CreateConstraint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr, + frame1, frame1rot, + frame2, frame2rot)); + m_enabled = true; + } + + public void Dispose() + { + if (m_enabled) + { + // BulletSimAPI.RemoveConstraint(m_world.ID, m_body1.ID, m_body2.ID); + BulletSimAPI.DestroyConstraint2(m_world.Ptr, m_constraint.Ptr); + m_enabled = false; + } + } + + public BulletBody Body1 { get { return m_body1; } } + public BulletBody Body2 { get { return m_body2; } } + + public bool SetLinearLimits(Vector3 low, Vector3 high) + { + bool ret = false; + if (m_enabled) + ret = BulletSimAPI.SetLinearLimits2(m_constraint.Ptr, low, high); + return ret; + } + + public bool SetAngularLimits(Vector3 low, Vector3 high) + { + bool ret = false; + if (m_enabled) + ret = BulletSimAPI.SetAngularLimits2(m_constraint.Ptr, low, high); + return ret; + } + + public bool UseFrameOffset(bool useOffset) + { + bool ret = false; + float onOff = useOffset ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse; + if (m_enabled) + ret = BulletSimAPI.UseFrameOffset2(m_constraint.Ptr, onOff); + return ret; + } + + public bool TranslationalLimitMotor(bool enable, float targetVelocity, float maxMotorForce) + { + bool ret = false; + float onOff = enable ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse; + if (m_enabled) + ret = BulletSimAPI.TranslationalLimitMotor2(m_constraint.Ptr, onOff, targetVelocity, maxMotorForce); + return ret; + } + + public bool CalculateTransforms() + { + bool ret = false; + if (m_enabled) + { + BulletSimAPI.CalculateTransforms2(m_constraint.Ptr); + ret = true; + } + return ret; + } +} +} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs new file mode 100755 index 0000000..6c66c5c --- /dev/null +++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs @@ -0,0 +1,178 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyrightD + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +using System; +using System.Collections.Generic; +using System.Text; +using log4net; +using OpenMetaverse; + +namespace OpenSim.Region.Physics.BulletSPlugin +{ + +public class BSConstraintCollection : IDisposable +{ + // private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + // private static readonly string LogHeader = "[CONSTRAINT COLLECTION]"; + + delegate bool ConstraintAction(BSConstraint constrain); + + private List m_constraints; + private BulletSim m_world; + + public BSConstraintCollection(BulletSim world) + { + m_world = world; + m_constraints = new List(); + } + + public void Dispose() + { + this.Clear(); + } + + public void Clear() + { + foreach (BSConstraint cons in m_constraints) + { + cons.Dispose(); + } + m_constraints.Clear(); + } + + public BSConstraint CreateConstraint(BulletSim world, BulletBody obj1, BulletBody obj2, + Vector3 frame1, Quaternion frame1rot, + Vector3 frame2, Quaternion frame2rot) + { + BSConstraint constrain = new BSConstraint(world, obj1, obj2, frame1, frame1rot, frame2, frame2rot); + + this.AddConstraint(constrain); + return constrain; + } + + public bool AddConstraint(BSConstraint cons) + { + // There is only one constraint between any bodies. Remove any old just to make sure. + RemoveAndDestroyConstraint(cons.Body1, cons.Body2); + + m_constraints.Add(cons); + + return true; + } + + // Get the constraint between two bodies. There can be only one the way we're using them. + public bool TryGetConstraint(BulletBody body1, BulletBody body2, out BSConstraint returnConstraint) + { + bool found = false; + BSConstraint foundConstraint = null; + + uint lookingID1 = body1.ID; + uint lookingID2 = body2.ID; + ForEachConstraint(delegate(BSConstraint constrain) + { + if ((constrain.Body1.ID == lookingID1 && constrain.Body2.ID == lookingID2) + || (constrain.Body1.ID == lookingID2 && constrain.Body2.ID == lookingID1)) + { + foundConstraint = constrain; + found = true; + } + return found; + }); + returnConstraint = foundConstraint; + return found; + } + + public bool RemoveAndDestroyConstraint(BulletBody body1, BulletBody body2) + { + // return BulletSimAPI.RemoveConstraint(m_world.ID, obj1.ID, obj2.ID); + + bool ret = false; + BSConstraint constrain; + + if (this.TryGetConstraint(body1, body2, out constrain)) + { + // remove the constraint from our collection + m_constraints.Remove(constrain); + // tell the engine that all its structures need to be freed + constrain.Dispose(); + // we destroyed something + ret = true; + } + + return ret; + } + + public bool RemoveAndDestroyConstraint(BulletBody body1) + { + // return BulletSimAPI.RemoveConstraintByID(m_world.ID, obj.ID); + + List toRemove = new List(); + uint lookingID = body1.ID; + ForEachConstraint(delegate(BSConstraint constrain) + { + if (constrain.Body1.ID == lookingID || constrain.Body2.ID == lookingID) + { + toRemove.Add(constrain); + } + return false; + }); + lock (m_constraints) + { + foreach (BSConstraint constrain in toRemove) + { + m_constraints.Remove(constrain); + constrain.Dispose(); + } + } + return (toRemove.Count > 0); + } + + public bool RecalculateAllConstraints() + { + foreach (BSConstraint constrain in m_constraints) + { + constrain.CalculateTransforms(); + } + return true; + } + + // Lock the constraint list and loop through it. + // The constraint action returns 'true' if it wants the loop aborted. + private void ForEachConstraint(ConstraintAction action) + { + lock (m_constraints) + { + foreach (BSConstraint constrain in m_constraints) + { + if (action(constrain)) + break; + } + } + } + + +} +} -- cgit v1.1 From bf6529db320bc7ab3fe292e3b7288c8f71636f6e Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 25 Jul 2012 10:35:34 -0700 Subject: BulletSim: Redo parameter specification so only one place has to change to have a parameter show up in the ini file and command line. Will make it much easier for the next person. --- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 626 ++++++++++++++---------- 1 file changed, 378 insertions(+), 248 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 7cc3fe3..07a377b 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -103,6 +103,17 @@ public class BSScene : PhysicsScene, IPhysicsParameters get { return m_sculptLOD; } } + private BulletSim m_worldSim; + public BulletSim World + { + get { return m_worldSim; } + } + private BSConstraintCollection m_constraintCollection; + public BSConstraintCollection Constraints + { + get { return m_constraintCollection; } + } + private int m_maxSubSteps; private float m_fixedTimeStep; private long m_simulationStep = 0; @@ -229,6 +240,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters m_maxCollisionsPerFrame, m_collisionArrayPinnedHandle.AddrOfPinnedObject(), m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject()); + // Initialization to support the transition to a new API which puts most of the logic + // into the C# code so it is easier to modify and add to. + m_worldSim = new BulletSim(m_worldID, BulletSimAPI.GetSimHandle2(m_worldID)); + m_constraintCollection = new BSConstraintCollection(World); + m_initialized = true; } @@ -237,116 +253,17 @@ public class BSScene : PhysicsScene, IPhysicsParameters private void GetInitialParameterValues(IConfigSource config) { ConfigurationParameters parms = new ConfigurationParameters(); + m_params[0] = parms; - _meshSculptedPrim = true; // mesh sculpted prims - _forceSimplePrimMeshing = false; // use complex meshing if called for - - m_meshLOD = 8f; - m_sculptLOD = 32f; - - shouldDebugLog = false; - m_detailedStatsStep = 0; // disabled - - m_maxSubSteps = 10; - m_fixedTimeStep = 1f / 60f; - m_maxCollisionsPerFrame = 2048; - m_maxUpdatesPerFrame = 2048; - m_maximumObjectMass = 10000.01f; - - PID_D = 2200f; - PID_P = 900f; - - parms.defaultFriction = 0.5f; - parms.defaultDensity = 10.000006836f; // Aluminum g/cm3 - parms.defaultRestitution = 0f; - parms.collisionMargin = 0.0f; - parms.gravity = -9.80665f; - - parms.linearDamping = 0.0f; - parms.angularDamping = 0.0f; - parms.deactivationTime = 0.2f; - parms.linearSleepingThreshold = 0.8f; - parms.angularSleepingThreshold = 1.0f; - parms.ccdMotionThreshold = 0.0f; // set to zero to disable - parms.ccdSweptSphereRadius = 0.0f; - parms.contactProcessingThreshold = 0.1f; - - parms.terrainFriction = 0.5f; - parms.terrainHitFraction = 0.8f; - parms.terrainRestitution = 0f; - parms.avatarFriction = 0.5f; - parms.avatarRestitution = 0.0f; - parms.avatarDensity = 60f; - parms.avatarCapsuleRadius = 0.37f; - parms.avatarCapsuleHeight = 1.5f; // 2.140599f - parms.avatarContactProcessingThreshold = 0.1f; - - parms.maxPersistantManifoldPoolSize = 0f; - parms.shouldDisableContactPoolDynamicAllocation = ConfigurationParameters.numericTrue; - parms.shouldForceUpdateAllAabbs = ConfigurationParameters.numericFalse; - parms.shouldRandomizeSolverOrder = ConfigurationParameters.numericFalse; - parms.shouldSplitSimulationIslands = ConfigurationParameters.numericFalse; - parms.shouldEnableFrictionCaching = ConfigurationParameters.numericFalse; - parms.numberOfSolverIterations = 0f; // means use default + SetParameterDefaultValues(); if (config != null) { // If there are specifications in the ini file, use those values - // WHEN ADDING OR UPDATING THIS SECTION, BE SURE TO UPDATE OpenSimDefaults.ini - // ALSO REMEMBER TO UPDATE THE RUNTIME SETTING OF THE PARAMETERS. IConfig pConfig = config.Configs["BulletSim"]; if (pConfig != null) { - _meshSculptedPrim = pConfig.GetBoolean("MeshSculptedPrim", _meshSculptedPrim); - _forceSimplePrimMeshing = pConfig.GetBoolean("ForceSimplePrimMeshing", _forceSimplePrimMeshing); - - shouldDebugLog = pConfig.GetBoolean("ShouldDebugLog", shouldDebugLog); - m_detailedStatsStep = pConfig.GetInt("DetailedStatsStep", m_detailedStatsStep); - - m_meshLOD = pConfig.GetFloat("MeshLevelOfDetail", m_meshLOD); - m_sculptLOD = pConfig.GetFloat("SculptLevelOfDetail", m_sculptLOD); - - m_maxSubSteps = pConfig.GetInt("MaxSubSteps", m_maxSubSteps); - m_fixedTimeStep = pConfig.GetFloat("FixedTimeStep", m_fixedTimeStep); - m_maxCollisionsPerFrame = pConfig.GetInt("MaxCollisionsPerFrame", m_maxCollisionsPerFrame); - m_maxUpdatesPerFrame = pConfig.GetInt("MaxUpdatesPerFrame", m_maxUpdatesPerFrame); - m_maximumObjectMass = pConfig.GetFloat("MaxObjectMass", m_maximumObjectMass); - - PID_D = pConfig.GetFloat("PIDDerivative", PID_D); - PID_P = pConfig.GetFloat("PIDProportional", PID_P); - - parms.defaultFriction = pConfig.GetFloat("DefaultFriction", parms.defaultFriction); - parms.defaultDensity = pConfig.GetFloat("DefaultDensity", parms.defaultDensity); - parms.defaultRestitution = pConfig.GetFloat("DefaultRestitution", parms.defaultRestitution); - parms.collisionMargin = pConfig.GetFloat("CollisionMargin", parms.collisionMargin); - parms.gravity = pConfig.GetFloat("Gravity", parms.gravity); - - parms.linearDamping = pConfig.GetFloat("LinearDamping", parms.linearDamping); - parms.angularDamping = pConfig.GetFloat("AngularDamping", parms.angularDamping); - parms.deactivationTime = pConfig.GetFloat("DeactivationTime", parms.deactivationTime); - parms.linearSleepingThreshold = pConfig.GetFloat("LinearSleepingThreshold", parms.linearSleepingThreshold); - parms.angularSleepingThreshold = pConfig.GetFloat("AngularSleepingThreshold", parms.angularSleepingThreshold); - parms.ccdMotionThreshold = pConfig.GetFloat("CcdMotionThreshold", parms.ccdMotionThreshold); - parms.ccdSweptSphereRadius = pConfig.GetFloat("CcdSweptSphereRadius", parms.ccdSweptSphereRadius); - parms.contactProcessingThreshold = pConfig.GetFloat("ContactProcessingThreshold", parms.contactProcessingThreshold); - - parms.terrainFriction = pConfig.GetFloat("TerrainFriction", parms.terrainFriction); - parms.terrainHitFraction = pConfig.GetFloat("TerrainHitFraction", parms.terrainHitFraction); - parms.terrainRestitution = pConfig.GetFloat("TerrainRestitution", parms.terrainRestitution); - parms.avatarFriction = pConfig.GetFloat("AvatarFriction", parms.avatarFriction); - parms.avatarRestitution = pConfig.GetFloat("AvatarRestitution", parms.avatarRestitution); - parms.avatarDensity = pConfig.GetFloat("AvatarDensity", parms.avatarDensity); - parms.avatarCapsuleRadius = pConfig.GetFloat("AvatarCapsuleRadius", parms.avatarCapsuleRadius); - parms.avatarCapsuleHeight = pConfig.GetFloat("AvatarCapsuleHeight", parms.avatarCapsuleHeight); - parms.avatarContactProcessingThreshold = pConfig.GetFloat("AvatarContactProcessingThreshold", parms.avatarContactProcessingThreshold); - - parms.maxPersistantManifoldPoolSize = pConfig.GetFloat("MaxPersistantManifoldPoolSize", parms.maxPersistantManifoldPoolSize); - parms.shouldDisableContactPoolDynamicAllocation = ParamBoolean(pConfig, "ShouldDisableContactPoolDynamicAllocation", parms.shouldDisableContactPoolDynamicAllocation); - parms.shouldForceUpdateAllAabbs = ParamBoolean(pConfig, "ShouldForceUpdateAllAabbs", parms.shouldForceUpdateAllAabbs); - parms.shouldRandomizeSolverOrder = ParamBoolean(pConfig, "ShouldRandomizeSolverOrder", parms.shouldRandomizeSolverOrder); - parms.shouldSplitSimulationIslands = ParamBoolean(pConfig, "ShouldSplitSimulationIslands", parms.shouldSplitSimulationIslands); - parms.shouldEnableFrictionCaching = ParamBoolean(pConfig, "ShouldEnableFrictionCaching", parms.shouldEnableFrictionCaching); - parms.numberOfSolverIterations = pConfig.GetFloat("NumberOfSolverIterations", parms.numberOfSolverIterations); + SetParameterConfigurationValues(pConfig); // Very detailed logging for physics debugging m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false); @@ -357,7 +274,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters m_vehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false); } } - m_params[0] = parms; } // A helper function that handles a true/false parameter and returns the proper float number encoding @@ -634,6 +550,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters // make sure no stepping happens while we're deleting stuff m_initialized = false; + if (m_constraintCollection != null) + { + m_constraintCollection.Dispose(); + m_constraintCollection = null; + } + foreach (KeyValuePair kvp in m_avatars) { kvp.Value.Destroy(); @@ -776,10 +698,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters } // The calls to the PhysicsActors can't directly call into the physics engine - // because it might be busy. We we delay changes to a known time. + // because it might be busy. We delay changes to a known time. // We rely on C#'s closure to save and restore the context for the delegate. public void TaintedObject(TaintCallback callback) { + if (!m_initialized) return; + lock (_taintLock) _taintedObjects.Add(callback); return; @@ -853,61 +777,350 @@ public class BSScene : PhysicsScene, IPhysicsParameters } #endregion Vehicles - #region Runtime settable parameters - public static PhysParameterEntry[] SettableParameters = new PhysParameterEntry[] + #region Parameters + + delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val); + delegate float ParamGet(BSScene scene); + delegate void ParamSet(BSScene scene, string paramName, uint localID, float val); + + private struct ParameterDefn { - new PhysParameterEntry("MeshLOD", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)"), - new PhysParameterEntry("SculptLOD", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)"), - new PhysParameterEntry("MaxSubStep", "In simulation step, maximum number of substeps"), - new PhysParameterEntry("FixedTimeStep", "In simulation step, seconds of one substep (1/60)"), - new PhysParameterEntry("MaxObjectMass", "Maximum object mass (10000.01)"), - new PhysParameterEntry("DetailedStats", "Frames between outputting detailed phys stats. Zero is off"), - - new PhysParameterEntry("DefaultFriction", "Friction factor used on new objects"), - new PhysParameterEntry("DefaultDensity", "Density for new objects" ), - new PhysParameterEntry("DefaultRestitution", "Bouncyness of an object" ), - // new PhysParameterEntry("CollisionMargin", "Margin around objects before collisions are calculated (must be zero!!)" ), - new PhysParameterEntry("Gravity", "Vertical force of gravity (negative means down)" ), - - new PhysParameterEntry("LinearDamping", "Factor to damp linear movement per second (0.0 - 1.0)" ), - new PhysParameterEntry("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)" ), - new PhysParameterEntry("DeactivationTime", "Seconds before considering an object potentially static" ), - new PhysParameterEntry("LinearSleepingThreshold", "Seconds to measure linear movement before considering static" ), - new PhysParameterEntry("AngularSleepingThreshold", "Seconds to measure angular movement before considering static" ), - new PhysParameterEntry("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" ), - new PhysParameterEntry("CcdSweptSphereRadius", "Continuious collision detection test radius" ), - new PhysParameterEntry("ContactProcessingThreshold", "Distance between contacts before doing collision check" ), - // Can only change the following at initialization time. Change the INI file and reboot. - new PhysParameterEntry("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default)"), - new PhysParameterEntry("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count"), - new PhysParameterEntry("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step"), - new PhysParameterEntry("ShouldRandomizeSolverOrder", "Enable for slightly better stacking interaction"), - new PhysParameterEntry("ShouldSplitSimulationIslands", "Enable splitting active object scanning islands"), - new PhysParameterEntry("ShouldEnableFrictionCaching", "Enable friction computation caching"), - new PhysParameterEntry("NumberOfSolverIterations", "Number of internal iterations (0 means default)"), - - new PhysParameterEntry("Friction", "Set friction parameter for a specific object" ), - new PhysParameterEntry("Restitution", "Set restitution parameter for a specific object" ), - - new PhysParameterEntry("Friction", "Set friction parameter for a specific object" ), - new PhysParameterEntry("Restitution", "Set restitution parameter for a specific object" ), - - new PhysParameterEntry("TerrainFriction", "Factor to reduce movement against terrain surface" ), - new PhysParameterEntry("TerrainHitFraction", "Distance to measure hit collisions" ), - new PhysParameterEntry("TerrainRestitution", "Bouncyness" ), - new PhysParameterEntry("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation." ), - new PhysParameterEntry("AvatarDensity", "Density of an avatar. Changed on avatar recreation." ), - new PhysParameterEntry("AvatarRestitution", "Bouncyness. Changed on avatar recreation." ), - new PhysParameterEntry("AvatarCapsuleRadius", "Radius of space around an avatar" ), - new PhysParameterEntry("AvatarCapsuleHeight", "Default height of space around avatar" ), - new PhysParameterEntry("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions") + public string name; + public string desc; + public float defaultValue; + public ParamUser userParam; + public ParamGet getter; + public ParamSet setter; + public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s) + { + name = n; + desc = d; + defaultValue = v; + userParam = u; + getter = g; + setter = s; + } + } + + // List of all of the externally visible parameters. + // For each parameter, this table maps a text name to getter and setters. + // A ParameterDefn() takes the following parameters: + // -- the text name of the parameter. This is used for console input and ini file. + // -- a short text description of the parameter. This shows up in the console listing. + // -- a delegate for fetching the parameter from the ini file. + // Should handle fetching the right type from the ini file and converting it. + // -- a delegate for getting the value as a float + // -- a delegate for setting the value from a float + // + // To add a new variable, it is best to find an existing definition and copy it. + private ParameterDefn[] ParameterDefinitions = + { + new ParameterDefn("MeshSculptedPrim", "Whether to create meshes for sculpties", + ConfigurationParameters.numericTrue, + (s,cf,p,v) => { s._meshSculptedPrim = cf.GetBoolean(p, s.BoolNumeric(v)); }, + (s) => { return s.NumericBool(s._meshSculptedPrim); }, + (s,p,l,v) => { s._meshSculptedPrim = s.BoolNumeric(v); } ), + new ParameterDefn("ForceSimplePrimMeshing", "If true, only use primitive meshes for objects", + ConfigurationParameters.numericFalse, + (s,cf,p,v) => { s._forceSimplePrimMeshing = cf.GetBoolean(p, s.BoolNumeric(v)); }, + (s) => { return s.NumericBool(s._forceSimplePrimMeshing); }, + (s,p,l,v) => { s._forceSimplePrimMeshing = s.BoolNumeric(v); } ), + + new ParameterDefn("MeshLOD", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)", + 8f, + (s,cf,p,v) => { s.m_meshLOD = cf.GetInt(p, (int)v); }, + (s) => { return (float)s.m_meshLOD; }, + (s,p,l,v) => { s.m_meshLOD = (int)v; } ), + new ParameterDefn("SculptLOD", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)", + 32, + (s,cf,p,v) => { s.m_sculptLOD = cf.GetInt(p, (int)v); }, + (s) => { return (float)s.m_sculptLOD; }, + (s,p,l,v) => { s.m_sculptLOD = (int)v; } ), + + new ParameterDefn("MaxSubStep", "In simulation step, maximum number of substeps", + 10f, + (s,cf,p,v) => { s.m_maxSubSteps = cf.GetInt(p, (int)v); }, + (s) => { return (float)s.m_maxSubSteps; }, + (s,p,l,v) => { s.m_maxSubSteps = (int)v; } ), + new ParameterDefn("FixedTimeStep", "In simulation step, seconds of one substep (1/60)", + 1f / 60f, + (s,cf,p,v) => { s.m_fixedTimeStep = cf.GetFloat(p, v); }, + (s) => { return (float)s.m_fixedTimeStep; }, + (s,p,l,v) => { s.m_fixedTimeStep = v; } ), + new ParameterDefn("MaxCollisionsPerFrame", "Max collisions returned at end of each frame", + 2048f, + (s,cf,p,v) => { s.m_maxCollisionsPerFrame = cf.GetInt(p, (int)v); }, + (s) => { return (float)s.m_maxCollisionsPerFrame; }, + (s,p,l,v) => { s.m_maxCollisionsPerFrame = (int)v; } ), + new ParameterDefn("MaxUpdatesPerFrame", "Max updates returned at end of each frame", + 8000f, + (s,cf,p,v) => { s.m_maxUpdatesPerFrame = cf.GetInt(p, (int)v); }, + (s) => { return (float)s.m_maxUpdatesPerFrame; }, + (s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ), + new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)", + 10000.01f, + (s,cf,p,v) => { s.m_maximumObjectMass = cf.GetFloat(p, v); }, + (s) => { return (float)s.m_maximumObjectMass; }, + (s,p,l,v) => { s.m_maximumObjectMass = v; } ), + + new ParameterDefn("PID_D", "Derivitive factor for motion smoothing", + 2200f, + (s,cf,p,v) => { s.PID_D = cf.GetFloat(p, v); }, + (s) => { return (float)s.PID_D; }, + (s,p,l,v) => { s.PID_D = v; } ), + new ParameterDefn("PID_P", "Parameteric factor for motion smoothing", + 900f, + (s,cf,p,v) => { s.PID_P = cf.GetFloat(p, v); }, + (s) => { return (float)s.PID_P; }, + (s,p,l,v) => { s.PID_P = v; } ), + + new ParameterDefn("DefaultFriction", "Friction factor used on new objects", + 0.5f, + (s,cf,p,v) => { s.m_params[0].defaultFriction = cf.GetFloat(p, v); }, + (s) => { return s.m_params[0].defaultFriction; }, + (s,p,l,v) => { s.m_params[0].defaultFriction = v; } ), + new ParameterDefn("DefaultDensity", "Density for new objects" , + 10.000006836f, // Aluminum g/cm3 + (s,cf,p,v) => { s.m_params[0].defaultDensity = cf.GetFloat(p, v); }, + (s) => { return s.m_params[0].defaultDensity; }, + (s,p,l,v) => { s.m_params[0].defaultDensity = v; } ), + new ParameterDefn("DefaultRestitution", "Bouncyness of an object" , + 0f, + (s,cf,p,v) => { s.m_params[0].defaultRestitution = cf.GetFloat(p, v); }, + (s) => { return s.m_params[0].defaultRestitution; }, + (s,p,l,v) => { s.m_params[0].defaultRestitution = v; } ), + new ParameterDefn("CollisionMargin", "Margin around objects before collisions are calculated (must be zero!)", + 0f, + (s,cf,p,v) => { s.m_params[0].collisionMargin = cf.GetFloat(p, v); }, + (s) => { return s.m_params[0].collisionMargin; }, + (s,p,l,v) => { s.m_params[0].collisionMargin = v; } ), + new ParameterDefn("Gravity", "Vertical force of gravity (negative means down)", + -9.80665f, + (s,cf,p,v) => { s.m_params[0].gravity = cf.GetFloat(p, v); }, + (s) => { return s.m_params[0].gravity; }, + (s,p,l,v) => { s.m_params[0].gravity = v; s.TaintedUpdateParameter(p,l,v); } ), + + + new ParameterDefn("LinearDamping", "Factor to damp linear movement per second (0.0 - 1.0)", + 0f, + (s,cf,p,v) => { s.m_params[0].linearDamping = cf.GetFloat(p, v); }, + (s) => { return s.m_params[0].linearDamping; }, + (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].linearDamping, p, l, v); } ), + new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)", + 0f, + (s,cf,p,v) => { s.m_params[0].angularDamping = cf.GetFloat(p, v); }, + (s) => { return s.m_params[0].angularDamping; }, + (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].angularDamping, p, l, v); } ), + new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static", + 0.2f, + (s,cf,p,v) => { s.m_params[0].deactivationTime = cf.GetFloat(p, v); }, + (s) => { return s.m_params[0].deactivationTime; }, + (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].deactivationTime, p, l, v); } ), + new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static", + 0.8f, + (s,cf,p,v) => { s.m_params[0].linearSleepingThreshold = cf.GetFloat(p, v); }, + (s) => { return s.m_params[0].linearSleepingThreshold; }, + (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].linearSleepingThreshold, p, l, v); } ), + new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static", + 1.0f, + (s,cf,p,v) => { s.m_params[0].angularSleepingThreshold = cf.GetFloat(p, v); }, + (s) => { return s.m_params[0].angularSleepingThreshold; }, + (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].angularSleepingThreshold, p, l, v); } ), + new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" , + 0f, // set to zero to disable + (s,cf,p,v) => { s.m_params[0].ccdMotionThreshold = cf.GetFloat(p, v); }, + (s) => { return s.m_params[0].ccdMotionThreshold; }, + (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].ccdMotionThreshold, p, l, v); } ), + new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" , + 0f, + (s,cf,p,v) => { s.m_params[0].ccdSweptSphereRadius = cf.GetFloat(p, v); }, + (s) => { return s.m_params[0].ccdSweptSphereRadius; }, + (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].ccdSweptSphereRadius, p, l, v); } ), + new ParameterDefn("ContactProcessingThreshold", "Distance between contacts before doing collision check" , + 0.1f, + (s,cf,p,v) => { s.m_params[0].contactProcessingThreshold = cf.GetFloat(p, v); }, + (s) => { return s.m_params[0].contactProcessingThreshold; }, + (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].contactProcessingThreshold, p, l, v); } ), + + new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" , + 0.5f, + (s,cf,p,v) => { s.m_params[0].terrainFriction = cf.GetFloat(p, v); }, + (s) => { return s.m_params[0].terrainFriction; }, + (s,p,l,v) => { s.m_params[0].terrainFriction = v; s.TaintedUpdateParameter(p,l,v); } ), + new ParameterDefn("TerrainHitFraction", "Distance to measure hit collisions" , + 0.8f, + (s,cf,p,v) => { s.m_params[0].terrainHitFraction = cf.GetFloat(p, v); }, + (s) => { return s.m_params[0].terrainHitFraction; }, + (s,p,l,v) => { s.m_params[0].terrainHitFraction = v; s.TaintedUpdateParameter(p,l,v); } ), + new ParameterDefn("TerrainRestitution", "Bouncyness" , + 0f, + (s,cf,p,v) => { s.m_params[0].terrainRestitution = cf.GetFloat(p, v); }, + (s) => { return s.m_params[0].terrainRestitution; }, + (s,p,l,v) => { s.m_params[0].terrainRestitution = v; s.TaintedUpdateParameter(p,l,v); } ), + new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.", + 0.5f, + (s,cf,p,v) => { s.m_params[0].avatarFriction = cf.GetFloat(p, v); }, + (s) => { return s.m_params[0].avatarFriction; }, + (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarFriction, p, l, v); } ), + new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation.", + 60f, + (s,cf,p,v) => { s.m_params[0].avatarDensity = cf.GetFloat(p, v); }, + (s) => { return s.m_params[0].avatarDensity; }, + (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarDensity, p, l, v); } ), + new ParameterDefn("AvatarRestitution", "Bouncyness. Changed on avatar recreation.", + 0f, + (s,cf,p,v) => { s.m_params[0].avatarRestitution = cf.GetFloat(p, v); }, + (s) => { return s.m_params[0].avatarRestitution; }, + (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarRestitution, p, l, v); } ), + new ParameterDefn("AvatarCapsuleRadius", "Radius of space around an avatar", + 0.37f, + (s,cf,p,v) => { s.m_params[0].avatarCapsuleRadius = cf.GetFloat(p, v); }, + (s) => { return s.m_params[0].avatarCapsuleRadius; }, + (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarCapsuleRadius, p, l, v); } ), + new ParameterDefn("AvatarCapsuleHeight", "Default height of space around avatar", + 1.5f, + (s,cf,p,v) => { s.m_params[0].avatarCapsuleHeight = cf.GetFloat(p, v); }, + (s) => { return s.m_params[0].avatarCapsuleHeight; }, + (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarCapsuleHeight, p, l, v); } ), + new ParameterDefn("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions", + 0.1f, + (s,cf,p,v) => { s.m_params[0].avatarContactProcessingThreshold = cf.GetFloat(p, v); }, + (s) => { return s.m_params[0].avatarContactProcessingThreshold; }, + (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarContactProcessingThreshold, p, l, v); } ), + + + new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default)", + 0f, // zero to disable + (s,cf,p,v) => { s.m_params[0].maxPersistantManifoldPoolSize = cf.GetFloat(p, v); }, + (s) => { return s.m_params[0].maxPersistantManifoldPoolSize; }, + (s,p,l,v) => { s.m_params[0].maxPersistantManifoldPoolSize = v; } ), + new ParameterDefn("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count", + ConfigurationParameters.numericTrue, + (s,cf,p,v) => { s.m_params[0].maxPersistantManifoldPoolSize = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, + (s) => { return s.m_params[0].shouldDisableContactPoolDynamicAllocation; }, + (s,p,l,v) => { s.m_params[0].shouldDisableContactPoolDynamicAllocation = v; } ), + new ParameterDefn("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step", + ConfigurationParameters.numericFalse, + (s,cf,p,v) => { s.m_params[0].shouldForceUpdateAllAabbs = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, + (s) => { return s.m_params[0].shouldForceUpdateAllAabbs; }, + (s,p,l,v) => { s.m_params[0].shouldForceUpdateAllAabbs = v; } ), + new ParameterDefn("ShouldRandomizeSolverOrder", "Enable for slightly better stacking interaction", + ConfigurationParameters.numericFalse, + (s,cf,p,v) => { s.m_params[0].shouldRandomizeSolverOrder = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, + (s) => { return s.m_params[0].shouldRandomizeSolverOrder; }, + (s,p,l,v) => { s.m_params[0].shouldRandomizeSolverOrder = v; } ), + new ParameterDefn("ShouldSplitSimulationIslands", "Enable splitting active object scanning islands", + ConfigurationParameters.numericFalse, + (s,cf,p,v) => { s.m_params[0].shouldSplitSimulationIslands = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, + (s) => { return s.m_params[0].shouldSplitSimulationIslands; }, + (s,p,l,v) => { s.m_params[0].shouldSplitSimulationIslands = v; } ), + new ParameterDefn("ShouldEnableFrictionCaching", "Enable friction computation caching", + ConfigurationParameters.numericFalse, + (s,cf,p,v) => { s.m_params[0].shouldEnableFrictionCaching = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, + (s) => { return s.m_params[0].shouldEnableFrictionCaching; }, + (s,p,l,v) => { s.m_params[0].shouldEnableFrictionCaching = v; } ), + new ParameterDefn("NumberOfSolverIterations", "Number of internal iterations (0 means default)", + 0f, // zero says use Bullet default + (s,cf,p,v) => { s.m_params[0].numberOfSolverIterations = cf.GetFloat(p, v); }, + (s) => { return s.m_params[0].numberOfSolverIterations; }, + (s,p,l,v) => { s.m_params[0].numberOfSolverIterations = v; } ), + + new ParameterDefn("DetailedStats", "Frames between outputting detailed phys stats. (0 is off)", + 0f, + (s,cf,p,v) => { s.m_detailedStatsStep = cf.GetInt(p, (int)v); }, + (s) => { return (float)s.m_detailedStatsStep; }, + (s,p,l,v) => { s.m_detailedStatsStep = (int)v; } ), + new ParameterDefn("ShouldDebugLog", "Enables detailed DEBUG log statements", + ConfigurationParameters.numericFalse, + (s,cf,p,v) => { s.shouldDebugLog = cf.GetBoolean(p, s.BoolNumeric(v)); }, + (s) => { return s.NumericBool(s.shouldDebugLog); }, + (s,p,l,v) => { s.shouldDebugLog = s.BoolNumeric(v); } ), }; + // Convert a boolean to our numeric true and false values + protected float NumericBool(bool b) + { + return (b ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse); + } + + // Convert numeric true and false values to a boolean + protected bool BoolNumeric(float b) + { + return (b == ConfigurationParameters.numericTrue ? true : false); + } + + // Search through the parameter definitions and return the matching + // ParameterDefn structure. + // Case does not matter as names are compared after converting to lower case. + // Returns 'false' if the parameter is not found. + private bool TryGetParameter(string paramName, out ParameterDefn defn) + { + bool ret = false; + ParameterDefn foundDefn = new ParameterDefn(); + string pName = paramName.ToLower(); + + foreach (ParameterDefn parm in ParameterDefinitions) + { + if (pName == parm.name.ToLower()) + { + foundDefn = parm; + ret = true; + break; + } + } + defn = foundDefn; + return ret; + } + + // Pass through the settable parameters and set the default values + private void SetParameterDefaultValues() + { + foreach (ParameterDefn parm in ParameterDefinitions) + { + parm.setter(this, parm.name, PhysParameterEntry.APPLY_TO_NONE, parm.defaultValue); + } + } + + // Get user set values out of the ini file. + private void SetParameterConfigurationValues(IConfig cfg) + { + foreach (ParameterDefn parm in ParameterDefinitions) + { + parm.userParam(this, cfg, parm.name, parm.defaultValue); + } + } + + private PhysParameterEntry[] SettableParameters = new PhysParameterEntry[1]; + + private void BuildParameterTable() + { + if (SettableParameters.Length < ParameterDefinitions.Length) + { + + List entries = new List(); + for (int ii = 0; ii < ParameterDefinitions.Length; ii++) + { + ParameterDefn pd = ParameterDefinitions[ii]; + entries.Add(new PhysParameterEntry(pd.name, pd.desc)); + } + + // make the list in alphabetical order for estetic reasons + entries.Sort(delegate(PhysParameterEntry ppe1, PhysParameterEntry ppe2) + { + return ppe1.name.CompareTo(ppe2.name); + }); + + SettableParameters = entries.ToArray(); + } + } + + #region IPhysicsParameters // Get the list of parameters this physics engine supports public PhysParameterEntry[] GetParameterList() { + BuildParameterTable(); return SettableParameters; } @@ -919,63 +1132,18 @@ public class BSScene : PhysicsScene, IPhysicsParameters // value activated ('terrainFriction' for instance). public bool SetPhysicsParameter(string parm, float val, uint localID) { - bool ret = true; - string lparm = parm.ToLower(); - switch (lparm) + bool ret = false; + ParameterDefn theParam; + if (TryGetParameter(parm, out theParam)) { - case "detailedstats": m_detailedStatsStep = (int)val; break; - - case "meshlod": m_meshLOD = (int)val; break; - case "sculptlod": m_sculptLOD = (int)val; break; - case "maxsubstep": m_maxSubSteps = (int)val; break; - case "fixedtimestep": m_fixedTimeStep = val; break; - case "maxobjectmass": m_maximumObjectMass = val; break; - - case "defaultfriction": m_params[0].defaultFriction = val; break; - case "defaultdensity": m_params[0].defaultDensity = val; break; - case "defaultrestitution": m_params[0].defaultRestitution = val; break; - case "collisionmargin": m_params[0].collisionMargin = val; break; - case "gravity": m_params[0].gravity = val; TaintedUpdateParameter(lparm, localID, val); break; - - case "lineardamping": UpdateParameterPrims(ref m_params[0].linearDamping, lparm, localID, val); break; - case "angulardamping": UpdateParameterPrims(ref m_params[0].angularDamping, lparm, localID, val); break; - case "deactivationtime": UpdateParameterPrims(ref m_params[0].deactivationTime, lparm, localID, val); break; - case "linearsleepingthreshold": UpdateParameterPrims(ref m_params[0].linearSleepingThreshold, lparm, localID, val); break; - case "angularsleepingthreshold": UpdateParameterPrims(ref m_params[0].angularDamping, lparm, localID, val); break; - case "ccdmotionthreshold": UpdateParameterPrims(ref m_params[0].ccdMotionThreshold, lparm, localID, val); break; - case "ccdsweptsphereradius": UpdateParameterPrims(ref m_params[0].ccdSweptSphereRadius, lparm, localID, val); break; - case "contactprocessingthreshold": UpdateParameterPrims(ref m_params[0].contactProcessingThreshold, lparm, localID, val); break; - // the following are used only at initialization time so setting them makes no sense - // case "maxPersistantmanifoldpoolSize": m_params[0].maxPersistantManifoldPoolSize = val; break; - // case "shoulddisablecontactpooldynamicallocation": m_params[0].shouldDisableContactPoolDynamicAllocation = val; break; - // case "shouldforceupdateallaabbs": m_params[0].shouldForceUpdateAllAabbs = val; break; - // case "shouldrandomizesolverorder": m_params[0].shouldRandomizeSolverOrder = val; break; - // case "shouldsplitsimulationislands": m_params[0].shouldSplitSimulationIslands = val; break; - // case "shouldenablefrictioncaching": m_params[0].shouldEnableFrictionCaching = val; break; - // case "numberofsolveriterations": m_params[0].numberOfSolverIterations = val; break; - - case "friction": TaintedUpdateParameter(lparm, localID, val); break; - case "restitution": TaintedUpdateParameter(lparm, localID, val); break; - - // set a terrain physical feature and cause terrain to be recalculated - case "terrainfriction": m_params[0].terrainFriction = val; TaintedUpdateParameter("terrain", 0, val); break; - case "terrainhitfraction": m_params[0].terrainHitFraction = val; TaintedUpdateParameter("terrain", 0, val); break; - case "terrainrestitution": m_params[0].terrainRestitution = val; TaintedUpdateParameter("terrain", 0, val); break; - // set an avatar physical feature and cause avatar(s) to be recalculated - case "avatarfriction": UpdateParameterAvatars(ref m_params[0].avatarFriction, "avatar", localID, val); break; - case "avatardensity": UpdateParameterAvatars(ref m_params[0].avatarDensity, "avatar", localID, val); break; - case "avatarrestitution": UpdateParameterAvatars(ref m_params[0].avatarRestitution, "avatar", localID, val); break; - case "avatarcapsuleradius": UpdateParameterAvatars(ref m_params[0].avatarCapsuleRadius, "avatar", localID, val); break; - case "avatarcapsuleheight": UpdateParameterAvatars(ref m_params[0].avatarCapsuleHeight, "avatar", localID, val); break; - case "avatarcontactprocessingthreshold": UpdateParameterAvatars(ref m_params[0].avatarContactProcessingThreshold, "avatar", localID, val); break; - - default: ret = false; break; + theParam.setter(this, parm, localID, val); + ret = true; } return ret; } // check to see if we are updating a parameter for a particular or all of the prims - private void UpdateParameterPrims(ref float loc, string parm, uint localID, float val) + protected void UpdateParameterPrims(ref float loc, string parm, uint localID, float val) { List operateOn; lock (m_prims) operateOn = new List(m_prims.Keys); @@ -983,7 +1151,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters } // check to see if we are updating a parameter for a particular or all of the avatars - private void UpdateParameterAvatars(ref float loc, string parm, uint localID, float val) + protected void UpdateParameterAvatars(ref float loc, string parm, uint localID, float val) { List operateOn; lock (m_avatars) operateOn = new List(m_avatars.Keys); @@ -994,7 +1162,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters // If the local ID is APPLY_TO_NONE, just change the default value // If the localID is APPLY_TO_ALL change the default value and apply the new value to all the lIDs // If the localID is a specific object, apply the parameter change to only that object - private void UpdateParameterSet(List lIDs, ref float defaultLoc, string parm, uint localID, float val) + protected void UpdateParameterSet(List lIDs, ref float defaultLoc, string parm, uint localID, float val) { switch (localID) { @@ -1021,7 +1189,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters } // schedule the actual updating of the paramter to when the phys engine is not busy - private void TaintedUpdateParameter(string parm, uint localID, float val) + protected void TaintedUpdateParameter(string parm, uint localID, float val) { uint xlocalID = localID; string xparm = parm.ToLower(); @@ -1036,50 +1204,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters public bool GetPhysicsParameter(string parm, out float value) { float val = 0f; - bool ret = true; - switch (parm.ToLower()) + bool ret = false; + ParameterDefn theParam; + if (TryGetParameter(parm, out theParam)) { - case "detailedstats": val = (int)m_detailedStatsStep; break; - case "meshlod": val = (float)m_meshLOD; break; - case "sculptlod": val = (float)m_sculptLOD; break; - case "maxsubstep": val = (float)m_maxSubSteps; break; - case "fixedtimestep": val = m_fixedTimeStep; break; - case "maxobjectmass": val = m_maximumObjectMass; break; - - case "defaultfriction": val = m_params[0].defaultFriction; break; - case "defaultdensity": val = m_params[0].defaultDensity; break; - case "defaultrestitution": val = m_params[0].defaultRestitution; break; - case "collisionmargin": val = m_params[0].collisionMargin; break; - case "gravity": val = m_params[0].gravity; break; - - case "lineardamping": val = m_params[0].linearDamping; break; - case "angulardamping": val = m_params[0].angularDamping; break; - case "deactivationtime": val = m_params[0].deactivationTime; break; - case "linearsleepingthreshold": val = m_params[0].linearSleepingThreshold; break; - case "angularsleepingthreshold": val = m_params[0].angularDamping; break; - case "ccdmotionthreshold": val = m_params[0].ccdMotionThreshold; break; - case "ccdsweptsphereradius": val = m_params[0].ccdSweptSphereRadius; break; - case "contactprocessingthreshold": val = m_params[0].contactProcessingThreshold; break; - case "maxPersistantmanifoldpoolSize": val = m_params[0].maxPersistantManifoldPoolSize; break; - case "shoulddisablecontactpooldynamicallocation": val = m_params[0].shouldDisableContactPoolDynamicAllocation; break; - case "shouldforceupdateallaabbs": val = m_params[0].shouldForceUpdateAllAabbs; break; - case "shouldrandomizesolverorder": val = m_params[0].shouldRandomizeSolverOrder; break; - case "shouldsplitsimulationislands": val = m_params[0].shouldSplitSimulationIslands; break; - case "shouldenablefrictioncaching": val = m_params[0].shouldEnableFrictionCaching; break; - case "numberofsolveriterations": val = m_params[0].numberOfSolverIterations; break; - - case "terrainfriction": val = m_params[0].terrainFriction; break; - case "terrainhitfraction": val = m_params[0].terrainHitFraction; break; - case "terrainrestitution": val = m_params[0].terrainRestitution; break; - - case "avatarfriction": val = m_params[0].avatarFriction; break; - case "avatardensity": val = m_params[0].avatarDensity; break; - case "avatarrestitution": val = m_params[0].avatarRestitution; break; - case "avatarcapsuleradius": val = m_params[0].avatarCapsuleRadius; break; - case "avatarcapsuleheight": val = m_params[0].avatarCapsuleHeight; break; - case "avatarcontactprocessingthreshold": val = m_params[0].avatarContactProcessingThreshold; break; - default: ret = false; break; - + val = theParam.getter(this); + ret = true; } value = val; return ret; -- cgit v1.1 From 75f7721b0c954f8dc0bbaac6c333aba52e275ea2 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 25 Jul 2012 10:42:02 -0700 Subject: BulletSim: small change to use the pointer to the bullet object for zeroing forces. --- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index ff87955..6c8ae2e 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -169,7 +169,7 @@ public sealed class BSPrim : PhysicsActor _parentPrim = null; } - // make sure there are no other prims are linked to me + // make sure there are no other prims linked to me UnlinkAllChildren(); // everything in the C# world will get garbage collected. Tell the C++ world to free stuff. @@ -341,11 +341,10 @@ public sealed class BSPrim : PhysicsActor _rotationalVelocity = OMV.Vector3.Zero; // Zero some other properties directly into the physics engine - BulletBody obj = new BulletBody(LocalID, BulletSimAPI.GetBodyHandleWorldID2(_scene.WorldID, LocalID)); - BulletSimAPI.SetVelocity2(obj.Ptr, OMV.Vector3.Zero); - BulletSimAPI.SetAngularVelocity2(obj.Ptr, OMV.Vector3.Zero); - BulletSimAPI.SetInterpolation2(obj.Ptr, OMV.Vector3.Zero, OMV.Vector3.Zero); - BulletSimAPI.ClearForces2(obj.Ptr); + BulletSimAPI.SetVelocity2(Body.Ptr, OMV.Vector3.Zero); + BulletSimAPI.SetAngularVelocity2(Body.Ptr, OMV.Vector3.Zero); + BulletSimAPI.SetInterpolation2(Body.Ptr, OMV.Vector3.Zero, OMV.Vector3.Zero); + BulletSimAPI.ClearForces2(Body.Ptr); } public override void LockAngularMotion(OMV.Vector3 axis) -- cgit v1.1 From d7add2940a38437e748ca74163bbf37acecfa04c Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 25 Jul 2012 14:52:17 -0700 Subject: BulletSim: add parameters for setting linkset constraint factors --- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 24 +++++++++--------------- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 25 +++++++++++++++++++++++-- 2 files changed, 32 insertions(+), 17 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 6c8ae2e..3be28e3 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -1295,10 +1295,9 @@ public sealed class BSPrim : PhysicsActor // relative to each other. void CreateLinkset() { - DebugLog("{0}: CreateLinkset. Root prim={1}, prims={2}", LogHeader, LocalID, _childrenPrims.Count+1); + // DebugLog("{0}: CreateLinkset. Root prim={1}, prims={2}", LogHeader, LocalID, _childrenPrims.Count+1); // remove any constraints that might be in place - DebugLog("{0}: CreateLinkset: RemoveConstraints between me and any children", LogHeader, LocalID); UnlinkAllChildren(); // create constraints between the root prim and each of the children @@ -1324,18 +1323,8 @@ public sealed class BSPrim : PhysicsActor // create a constraint that allows no freedom of movement between the two objects // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 - DebugLog("{0}: CreateLinkset: Adding a constraint between root prim {1} and child prim {2}", LogHeader, LocalID, childPrim.LocalID); + // DebugLog("{0}: CreateLinkset: Adding a constraint between root prim {1} and child prim {2}", LogHeader, LocalID, childPrim.LocalID); DetailLog("{0},LinkAChildToMe,taint,root={1},child={2}", LocalID, LocalID, childPrim.LocalID); - /* - BulletSimAPI.AddConstraint(_scene.WorldID, LocalID, childPrim.LocalID, - childRelativePosition, - childRelativeRotation, - OMV.Vector3.Zero, - OMV.Quaternion.Identity, - OMV.Vector3.Zero, OMV.Vector3.Zero, - OMV.Vector3.Zero, OMV.Vector3.Zero); - */ - // BSConstraint constrain = new BSConstraint(_scene.World, this.Body, childPrim.Body, BSConstraint constrain = _scene.Constraints.CreateConstraint( _scene.World, this.Body, childPrim.Body, childRelativePosition, @@ -1346,8 +1335,13 @@ public sealed class BSPrim : PhysicsActor constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); // tweek the constraint to increase stability - constrain.UseFrameOffset(true); - constrain.TranslationalLimitMotor(true, 5f, 0.1f); + constrain.UseFrameOffset(_scene.BoolNumeric(_scene.Params.linkConstraintUseFrameOffset)); + if (_scene.BoolNumeric(_scene.Params.linkConstraintEnableTransMotor)) + { + constrain.TranslationalLimitMotor(true, + _scene.Params.linkConstraintTransMotorMaxVel, + _scene.Params.linkConstraintTransMotorMaxForce); + } } // Remove linkage between myself and a particular child diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 07a377b..a1587a8 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -1025,6 +1025,27 @@ public class BSScene : PhysicsScene, IPhysicsParameters (s) => { return s.m_params[0].numberOfSolverIterations; }, (s,p,l,v) => { s.m_params[0].numberOfSolverIterations = v; } ), + new ParameterDefn("LinkConstraintUseFrameOffset", "For linksets built with constraints, enable frame offsetFor linksets built with constraints, enable frame offset.", + ConfigurationParameters.numericTrue, + (s,cf,p,v) => { s.m_params[0].linkConstraintUseFrameOffset = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, + (s) => { return s.m_params[0].linkConstraintUseFrameOffset; }, + (s,p,l,v) => { s.m_params[0].linkConstraintUseFrameOffset = v; } ), + new ParameterDefn("LinkConstraintEnableTransMotor", "Whether to enable translational motor on linkset constraints", + ConfigurationParameters.numericTrue, + (s,cf,p,v) => { s.m_params[0].linkConstraintEnableTransMotor = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, + (s) => { return s.m_params[0].linkConstraintEnableTransMotor; }, + (s,p,l,v) => { s.m_params[0].linkConstraintEnableTransMotor = v; } ), + new ParameterDefn("LinkConstraintTransMotorMaxVel", "Maximum velocity to be applied by translational motor in linkset constraints", + 5.0f, + (s,cf,p,v) => { s.m_params[0].linkConstraintTransMotorMaxVel = cf.GetFloat(p, v); }, + (s) => { return s.m_params[0].linkConstraintTransMotorMaxVel; }, + (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxVel = v; } ), + new ParameterDefn("LinkConstraintTransMotorMaxForce", "Maximum force to be applied by translational motor in linkset constraints", + 0.1f, + (s,cf,p,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = cf.GetFloat(p, v); }, + (s) => { return s.m_params[0].linkConstraintTransMotorMaxForce; }, + (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = v; } ), + new ParameterDefn("DetailedStats", "Frames between outputting detailed phys stats. (0 is off)", 0f, (s,cf,p,v) => { s.m_detailedStatsStep = cf.GetInt(p, (int)v); }, @@ -1039,13 +1060,13 @@ public class BSScene : PhysicsScene, IPhysicsParameters }; // Convert a boolean to our numeric true and false values - protected float NumericBool(bool b) + public float NumericBool(bool b) { return (b ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse); } // Convert numeric true and false values to a boolean - protected bool BoolNumeric(float b) + public bool BoolNumeric(float b) { return (b == ConfigurationParameters.numericTrue ? true : false); } -- cgit v1.1 From 0a4c080e63d3159f4943a164a2085cc6a41fac80 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 25 Jul 2012 14:59:00 -0700 Subject: BulletSim: fix line endings in newly added files (Is it DOS or is it UNIX? Only it's hairdresser knows for sure) --- .../Region/Physics/BulletSPlugin/BSConstraint.cs | 246 +++++++------- .../BulletSPlugin/BSConstraintCollection.cs | 356 ++++++++++----------- 2 files changed, 301 insertions(+), 301 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs index ced8565..1966395 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs @@ -1,123 +1,123 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Text; -using OpenMetaverse; - -namespace OpenSim.Region.Physics.BulletSPlugin -{ - -public class BSConstraint : IDisposable -{ - private BulletSim m_world; - private BulletBody m_body1; - private BulletBody m_body2; - private BulletConstraint m_constraint; - private bool m_enabled = false; - - public BSConstraint(BulletSim world, BulletBody obj1, BulletBody obj2, - Vector3 frame1, Quaternion frame1rot, - Vector3 frame2, Quaternion frame2rot - ) - { - m_world = world; - m_body1 = obj1; - m_body2 = obj2; - /* - BulletSimAPI.AddConstraint(world.ID, m_body1.ID, m_body2.ID, - frame1, frame1rot, - frame2, frame2rot, - linearLow, linearHigh, - angularLow, angularHigh - ); - */ - m_constraint = new BulletConstraint(BulletSimAPI.CreateConstraint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr, - frame1, frame1rot, - frame2, frame2rot)); - m_enabled = true; - } - - public void Dispose() - { - if (m_enabled) - { - // BulletSimAPI.RemoveConstraint(m_world.ID, m_body1.ID, m_body2.ID); - BulletSimAPI.DestroyConstraint2(m_world.Ptr, m_constraint.Ptr); - m_enabled = false; - } - } - - public BulletBody Body1 { get { return m_body1; } } - public BulletBody Body2 { get { return m_body2; } } - - public bool SetLinearLimits(Vector3 low, Vector3 high) - { - bool ret = false; - if (m_enabled) - ret = BulletSimAPI.SetLinearLimits2(m_constraint.Ptr, low, high); - return ret; - } - - public bool SetAngularLimits(Vector3 low, Vector3 high) - { - bool ret = false; - if (m_enabled) - ret = BulletSimAPI.SetAngularLimits2(m_constraint.Ptr, low, high); - return ret; - } - - public bool UseFrameOffset(bool useOffset) - { - bool ret = false; - float onOff = useOffset ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse; - if (m_enabled) - ret = BulletSimAPI.UseFrameOffset2(m_constraint.Ptr, onOff); - return ret; - } - - public bool TranslationalLimitMotor(bool enable, float targetVelocity, float maxMotorForce) - { - bool ret = false; - float onOff = enable ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse; - if (m_enabled) - ret = BulletSimAPI.TranslationalLimitMotor2(m_constraint.Ptr, onOff, targetVelocity, maxMotorForce); - return ret; - } - - public bool CalculateTransforms() - { - bool ret = false; - if (m_enabled) - { - BulletSimAPI.CalculateTransforms2(m_constraint.Ptr); - ret = true; - } - return ret; - } -} -} +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyrightD + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +using System; +using System.Collections.Generic; +using System.Text; +using OpenMetaverse; + +namespace OpenSim.Region.Physics.BulletSPlugin +{ + +public class BSConstraint : IDisposable +{ + private BulletSim m_world; + private BulletBody m_body1; + private BulletBody m_body2; + private BulletConstraint m_constraint; + private bool m_enabled = false; + + public BSConstraint(BulletSim world, BulletBody obj1, BulletBody obj2, + Vector3 frame1, Quaternion frame1rot, + Vector3 frame2, Quaternion frame2rot + ) + { + m_world = world; + m_body1 = obj1; + m_body2 = obj2; + /* + BulletSimAPI.AddConstraint(world.ID, m_body1.ID, m_body2.ID, + frame1, frame1rot, + frame2, frame2rot, + linearLow, linearHigh, + angularLow, angularHigh + ); + */ + m_constraint = new BulletConstraint(BulletSimAPI.CreateConstraint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr, + frame1, frame1rot, + frame2, frame2rot)); + m_enabled = true; + } + + public void Dispose() + { + if (m_enabled) + { + // BulletSimAPI.RemoveConstraint(m_world.ID, m_body1.ID, m_body2.ID); + BulletSimAPI.DestroyConstraint2(m_world.Ptr, m_constraint.Ptr); + m_enabled = false; + } + } + + public BulletBody Body1 { get { return m_body1; } } + public BulletBody Body2 { get { return m_body2; } } + + public bool SetLinearLimits(Vector3 low, Vector3 high) + { + bool ret = false; + if (m_enabled) + ret = BulletSimAPI.SetLinearLimits2(m_constraint.Ptr, low, high); + return ret; + } + + public bool SetAngularLimits(Vector3 low, Vector3 high) + { + bool ret = false; + if (m_enabled) + ret = BulletSimAPI.SetAngularLimits2(m_constraint.Ptr, low, high); + return ret; + } + + public bool UseFrameOffset(bool useOffset) + { + bool ret = false; + float onOff = useOffset ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse; + if (m_enabled) + ret = BulletSimAPI.UseFrameOffset2(m_constraint.Ptr, onOff); + return ret; + } + + public bool TranslationalLimitMotor(bool enable, float targetVelocity, float maxMotorForce) + { + bool ret = false; + float onOff = enable ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse; + if (m_enabled) + ret = BulletSimAPI.TranslationalLimitMotor2(m_constraint.Ptr, onOff, targetVelocity, maxMotorForce); + return ret; + } + + public bool CalculateTransforms() + { + bool ret = false; + if (m_enabled) + { + BulletSimAPI.CalculateTransforms2(m_constraint.Ptr); + ret = true; + } + return ret; + } +} +} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs index 6c66c5c..a2650fb 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs @@ -1,178 +1,178 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Text; -using log4net; -using OpenMetaverse; - -namespace OpenSim.Region.Physics.BulletSPlugin -{ - -public class BSConstraintCollection : IDisposable -{ - // private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - // private static readonly string LogHeader = "[CONSTRAINT COLLECTION]"; - - delegate bool ConstraintAction(BSConstraint constrain); - - private List m_constraints; - private BulletSim m_world; - - public BSConstraintCollection(BulletSim world) - { - m_world = world; - m_constraints = new List(); - } - - public void Dispose() - { - this.Clear(); - } - - public void Clear() - { - foreach (BSConstraint cons in m_constraints) - { - cons.Dispose(); - } - m_constraints.Clear(); - } - - public BSConstraint CreateConstraint(BulletSim world, BulletBody obj1, BulletBody obj2, - Vector3 frame1, Quaternion frame1rot, - Vector3 frame2, Quaternion frame2rot) - { - BSConstraint constrain = new BSConstraint(world, obj1, obj2, frame1, frame1rot, frame2, frame2rot); - - this.AddConstraint(constrain); - return constrain; - } - - public bool AddConstraint(BSConstraint cons) - { - // There is only one constraint between any bodies. Remove any old just to make sure. - RemoveAndDestroyConstraint(cons.Body1, cons.Body2); - - m_constraints.Add(cons); - - return true; - } - - // Get the constraint between two bodies. There can be only one the way we're using them. - public bool TryGetConstraint(BulletBody body1, BulletBody body2, out BSConstraint returnConstraint) - { - bool found = false; - BSConstraint foundConstraint = null; - - uint lookingID1 = body1.ID; - uint lookingID2 = body2.ID; - ForEachConstraint(delegate(BSConstraint constrain) - { - if ((constrain.Body1.ID == lookingID1 && constrain.Body2.ID == lookingID2) - || (constrain.Body1.ID == lookingID2 && constrain.Body2.ID == lookingID1)) - { - foundConstraint = constrain; - found = true; - } - return found; - }); - returnConstraint = foundConstraint; - return found; - } - - public bool RemoveAndDestroyConstraint(BulletBody body1, BulletBody body2) - { - // return BulletSimAPI.RemoveConstraint(m_world.ID, obj1.ID, obj2.ID); - - bool ret = false; - BSConstraint constrain; - - if (this.TryGetConstraint(body1, body2, out constrain)) - { - // remove the constraint from our collection - m_constraints.Remove(constrain); - // tell the engine that all its structures need to be freed - constrain.Dispose(); - // we destroyed something - ret = true; - } - - return ret; - } - - public bool RemoveAndDestroyConstraint(BulletBody body1) - { - // return BulletSimAPI.RemoveConstraintByID(m_world.ID, obj.ID); - - List toRemove = new List(); - uint lookingID = body1.ID; - ForEachConstraint(delegate(BSConstraint constrain) - { - if (constrain.Body1.ID == lookingID || constrain.Body2.ID == lookingID) - { - toRemove.Add(constrain); - } - return false; - }); - lock (m_constraints) - { - foreach (BSConstraint constrain in toRemove) - { - m_constraints.Remove(constrain); - constrain.Dispose(); - } - } - return (toRemove.Count > 0); - } - - public bool RecalculateAllConstraints() - { - foreach (BSConstraint constrain in m_constraints) - { - constrain.CalculateTransforms(); - } - return true; - } - - // Lock the constraint list and loop through it. - // The constraint action returns 'true' if it wants the loop aborted. - private void ForEachConstraint(ConstraintAction action) - { - lock (m_constraints) - { - foreach (BSConstraint constrain in m_constraints) - { - if (action(constrain)) - break; - } - } - } - - -} -} +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyrightD + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +using System; +using System.Collections.Generic; +using System.Text; +using log4net; +using OpenMetaverse; + +namespace OpenSim.Region.Physics.BulletSPlugin +{ + +public class BSConstraintCollection : IDisposable +{ + // private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + // private static readonly string LogHeader = "[CONSTRAINT COLLECTION]"; + + delegate bool ConstraintAction(BSConstraint constrain); + + private List m_constraints; + private BulletSim m_world; + + public BSConstraintCollection(BulletSim world) + { + m_world = world; + m_constraints = new List(); + } + + public void Dispose() + { + this.Clear(); + } + + public void Clear() + { + foreach (BSConstraint cons in m_constraints) + { + cons.Dispose(); + } + m_constraints.Clear(); + } + + public BSConstraint CreateConstraint(BulletSim world, BulletBody obj1, BulletBody obj2, + Vector3 frame1, Quaternion frame1rot, + Vector3 frame2, Quaternion frame2rot) + { + BSConstraint constrain = new BSConstraint(world, obj1, obj2, frame1, frame1rot, frame2, frame2rot); + + this.AddConstraint(constrain); + return constrain; + } + + public bool AddConstraint(BSConstraint cons) + { + // There is only one constraint between any bodies. Remove any old just to make sure. + RemoveAndDestroyConstraint(cons.Body1, cons.Body2); + + m_constraints.Add(cons); + + return true; + } + + // Get the constraint between two bodies. There can be only one the way we're using them. + public bool TryGetConstraint(BulletBody body1, BulletBody body2, out BSConstraint returnConstraint) + { + bool found = false; + BSConstraint foundConstraint = null; + + uint lookingID1 = body1.ID; + uint lookingID2 = body2.ID; + ForEachConstraint(delegate(BSConstraint constrain) + { + if ((constrain.Body1.ID == lookingID1 && constrain.Body2.ID == lookingID2) + || (constrain.Body1.ID == lookingID2 && constrain.Body2.ID == lookingID1)) + { + foundConstraint = constrain; + found = true; + } + return found; + }); + returnConstraint = foundConstraint; + return found; + } + + public bool RemoveAndDestroyConstraint(BulletBody body1, BulletBody body2) + { + // return BulletSimAPI.RemoveConstraint(m_world.ID, obj1.ID, obj2.ID); + + bool ret = false; + BSConstraint constrain; + + if (this.TryGetConstraint(body1, body2, out constrain)) + { + // remove the constraint from our collection + m_constraints.Remove(constrain); + // tell the engine that all its structures need to be freed + constrain.Dispose(); + // we destroyed something + ret = true; + } + + return ret; + } + + public bool RemoveAndDestroyConstraint(BulletBody body1) + { + // return BulletSimAPI.RemoveConstraintByID(m_world.ID, obj.ID); + + List toRemove = new List(); + uint lookingID = body1.ID; + ForEachConstraint(delegate(BSConstraint constrain) + { + if (constrain.Body1.ID == lookingID || constrain.Body2.ID == lookingID) + { + toRemove.Add(constrain); + } + return false; + }); + lock (m_constraints) + { + foreach (BSConstraint constrain in toRemove) + { + m_constraints.Remove(constrain); + constrain.Dispose(); + } + } + return (toRemove.Count > 0); + } + + public bool RecalculateAllConstraints() + { + foreach (BSConstraint constrain in m_constraints) + { + constrain.CalculateTransforms(); + } + return true; + } + + // Lock the constraint list and loop through it. + // The constraint action returns 'true' if it wants the loop aborted. + private void ForEachConstraint(ConstraintAction action) + { + lock (m_constraints) + { + foreach (BSConstraint constrain in m_constraints) + { + if (action(constrain)) + break; + } + } + } + + +} +} -- cgit v1.1 From 9ca1075e7e7fd1dea92a99a2d54fdc98c3389ccb Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 25 Jul 2012 16:21:14 -0700 Subject: BulletSim: remove unused, commented out code in BSConstraint --- OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs | 8 -------- 1 file changed, 8 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs index 1966395..fbb9e21 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs @@ -48,14 +48,6 @@ public class BSConstraint : IDisposable m_world = world; m_body1 = obj1; m_body2 = obj2; - /* - BulletSimAPI.AddConstraint(world.ID, m_body1.ID, m_body2.ID, - frame1, frame1rot, - frame2, frame2rot, - linearLow, linearHigh, - angularLow, angularHigh - ); - */ m_constraint = new BulletConstraint(BulletSimAPI.CreateConstraint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr, frame1, frame1rot, frame2, frame2rot)); -- cgit v1.1 From c1503205c028437507e2b8e4ab90e1258b1e9d60 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Thu, 26 Jul 2012 15:27:18 -0700 Subject: Add a Dispose() of the physics engine when a scene is being shutdown. --- OpenSim/Region/Framework/Scenes/Scene.cs | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'OpenSim') diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 24f62e3..1734704 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1222,6 +1222,15 @@ namespace OpenSim.Region.Framework.Scenes m_sceneGraph.Close(); + if (PhysicsScene != null) + { + PhysicsScene phys = PhysicsScene; + // remove the physics engine from both Scene and SceneGraph + PhysicsScene = null; + phys.Dispose(); + phys = null; + } + if (!GridService.DeregisterRegion(RegionInfo.RegionID)) m_log.WarnFormat("[SCENE]: Deregister from grid failed for region {0}", Name); -- cgit v1.1 From 66824dd18c331423914e0df414edb662ddf43869 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 26 Jul 2012 23:44:29 +0100 Subject: When copying items, copy the item description field instead of the asset description field. If we copy the asset description then we will only ever replicate the very first description, if there was one, not any subsequent changes. Thanks to Oren Hurvitz of Kitely for this patch from http://opensimulator.org/mantis/view.php?id=6107 I have adapted it slightly to change the order of arguments (name before description rather than vice-versa) and slightly improve some method doc. --- .../InventoryAccess/InventoryAccessModule.cs | 5 +- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 69 ++++++++++++++-------- 2 files changed, 49 insertions(+), 25 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index 7d51eed..8b34c28 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -204,8 +204,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess AssetBase asset = m_Scene.CreateAsset(name, description, assetType, data, remoteClient.AgentId); m_Scene.AssetService.Store(asset); - - m_Scene.CreateNewInventoryItem(remoteClient, remoteClient.AgentId.ToString(), string.Empty, folderID, asset.Name, 0, callbackID, asset, invType, nextOwnerMask, creationDate); + m_Scene.CreateNewInventoryItem( + remoteClient, remoteClient.AgentId.ToString(), string.Empty, folderID, + name, description, 0, callbackID, asset, invType, nextOwnerMask, creationDate); } else { diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index e413281..d18fffd 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -814,16 +814,20 @@ namespace OpenSim.Region.Framework.Scenes && oldAgentID == LibraryService.LibraryRootFolder.Owner)) { CreateNewInventoryItem( - remoteClient, item.CreatorId, item.CreatorData, newFolderID, newName, item.Flags, callbackID, asset, (sbyte)item.InvType, - item.BasePermissions, item.CurrentPermissions, item.EveryOnePermissions, item.NextPermissions, item.GroupPermissions, Util.UnixTimeSinceEpoch()); + remoteClient, item.CreatorId, item.CreatorData, newFolderID, + newName, item.Description, item.Flags, callbackID, asset, (sbyte)item.InvType, + item.BasePermissions, item.CurrentPermissions, item.EveryOnePermissions, + item.NextPermissions, item.GroupPermissions, Util.UnixTimeSinceEpoch()); } else { // If item is transfer or permissions are off or calling agent is allowed to copy item owner's inventory item. - if (((item.CurrentPermissions & (uint)PermissionMask.Transfer) != 0) && (m_permissions.BypassPermissions() || m_permissions.CanCopyUserInventory(remoteClient.AgentId, oldItemID))) + if (((item.CurrentPermissions & (uint)PermissionMask.Transfer) != 0) + && (m_permissions.BypassPermissions() + || m_permissions.CanCopyUserInventory(remoteClient.AgentId, oldItemID))) { CreateNewInventoryItem( - remoteClient, item.CreatorId, item.CreatorData, newFolderID, newName, item.Flags, callbackID, + remoteClient, item.CreatorId, item.CreatorData, newFolderID, newName, item.Description, item.Flags, callbackID, asset, (sbyte) item.InvType, item.NextPermissions, item.NextPermissions, item.EveryOnePermissions & item.NextPermissions, item.NextPermissions, item.GroupPermissions, Util.UnixTimeSinceEpoch()); @@ -870,32 +874,50 @@ namespace OpenSim.Region.Framework.Scenes /// /// Create a new inventory item. /// - /// - /// - /// - /// - /// - /// - public void CreateNewInventoryItem(IClientAPI remoteClient, string creatorID, string creatorData, UUID folderID, string name, uint flags, uint callbackID, - AssetBase asset, sbyte invType, uint nextOwnerMask, int creationDate) + /// Client creating this inventory item. + /// + /// + /// UUID of folder in which this item should be placed. + /// Item name. + /// Item description. + /// Item flags + /// Generated by the client. + /// Asset to which this item refers. + /// Type of inventory item. + /// Next owner pemrissions mask. + /// Unix timestamp at which this item was created. + public void CreateNewInventoryItem( + IClientAPI remoteClient, string creatorID, string creatorData, UUID folderID, + string name, string description, uint flags, uint callbackID, + AssetBase asset, sbyte invType, uint nextOwnerMask, int creationDate) { CreateNewInventoryItem( - remoteClient, creatorID, creatorData, folderID, name, flags, callbackID, asset, invType, + remoteClient, creatorID, creatorData, folderID, name, description, flags, callbackID, asset, invType, (uint)PermissionMask.All, (uint)PermissionMask.All, 0, nextOwnerMask, 0, creationDate); } /// /// Create a new Inventory Item /// - /// - /// - /// - /// - /// - /// - /// + /// Client creating this inventory item. + /// + /// + /// UUID of folder in which this item should be placed. + /// Item name. + /// Item description. + /// Item flags + /// Generated by the client. + /// Asset to which this item refers. + /// Type of inventory item. + /// Base permissions mask. + /// Current permissions mask. + /// Everyone permissions mask. + /// Next owner pemrissions mask. + /// Group permissions mask. + /// Unix timestamp at which this item was created. private void CreateNewInventoryItem( - IClientAPI remoteClient, string creatorID, string creatorData, UUID folderID, string name, uint flags, uint callbackID, AssetBase asset, sbyte invType, + IClientAPI remoteClient, string creatorID, string creatorData, UUID folderID, + string name, string description, uint flags, uint callbackID, AssetBase asset, sbyte invType, uint baseMask, uint currentMask, uint everyoneMask, uint nextOwnerMask, uint groupMask, int creationDate) { InventoryItemBase item = new InventoryItemBase(); @@ -904,8 +926,8 @@ namespace OpenSim.Region.Framework.Scenes item.CreatorData = creatorData; item.ID = UUID.Random(); item.AssetID = asset.FullID; - item.Description = asset.Description; item.Name = name; + item.Description = description; item.Flags = flags; item.AssetType = asset.Type; item.InvType = invType; @@ -987,7 +1009,8 @@ namespace OpenSim.Region.Framework.Scenes asset.Description = description; CreateNewInventoryItem( - remoteClient, remoteClient.AgentId.ToString(), string.Empty, folderID, name, 0, callbackID, asset, invType, + remoteClient, remoteClient.AgentId.ToString(), string.Empty, folderID, + name, description, 0, callbackID, asset, invType, (uint)PermissionMask.All, (uint)PermissionMask.All, (uint)PermissionMask.All, (uint)PermissionMask.All, (uint)PermissionMask.All, Util.UnixTimeSinceEpoch()); } -- cgit v1.1 From 9e914f5c321d5588b196221343e3bc9ed9735f64 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Thu, 26 Jul 2012 16:03:15 -0700 Subject: Add check so Ode does not try to simulate after it has been Dispose()'ed. Fixes exception that happens when shutting down region (improvements from last patch) --- OpenSim/Region/Physics/OdePlugin/OdeScene.cs | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'OpenSim') diff --git a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs index 32e81e2..0db936f 100644 --- a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs +++ b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs @@ -489,6 +489,8 @@ namespace OpenSim.Region.Physics.OdePlugin /// internal Object OdeLock = new Object(); + private bool _worldInitialized = false; + public IMesher mesher; private IConfigSource m_config; @@ -875,6 +877,8 @@ namespace OpenSim.Region.Physics.OdePlugin staticPrimspace[i, j] = IntPtr.Zero; } } + + _worldInitialized = true; } // internal void waitForSpaceUnlock(IntPtr space) @@ -2896,6 +2900,8 @@ namespace OpenSim.Region.Physics.OdePlugin /// The number of frames simulated over that period. public override float Simulate(float timeStep) { + if (!_worldInitialized) return 11f; + int startFrameTick = CollectStats ? Util.EnvironmentTickCount() : 0; int tempTick = 0, tempTick2 = 0; @@ -4017,6 +4023,8 @@ namespace OpenSim.Region.Physics.OdePlugin public override void Dispose() { + _worldInitialized = false; + m_rayCastManager.Dispose(); m_rayCastManager = null; @@ -4037,6 +4045,7 @@ namespace OpenSim.Region.Physics.OdePlugin d.WorldDestroy(world); //d.CloseODE(); } + } public override Dictionary GetTopColliders() -- cgit v1.1 From 7d30637d51c64a582cc55d41546af8f0cfc889ba Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Thu, 26 Jul 2012 14:54:57 -0700 Subject: BulletSim: refactor all the linkset logic out of the prim class and into its own class. The BulletSim data structures track individual prims as linksets of 1 so most of the prim code is not different between a linked and unlinked object. --- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 308 +++++++++++++++++++ OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 327 ++++++--------------- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 7 +- .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 2 +- 4 files changed, 409 insertions(+), 235 deletions(-) create mode 100755 OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs (limited to 'OpenSim') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs new file mode 100755 index 0000000..a1027ee --- /dev/null +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -0,0 +1,308 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyrightD + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +using System; +using System.Collections.Generic; +using System.Text; + +using OMV = OpenMetaverse; + +namespace OpenSim.Region.Physics.BulletSPlugin +{ +public class BSLinkset +{ + private static string LogHeader = "[BULLETSIM LINKSET]"; + + private BSPrim m_linksetRoot; + public BSPrim Root { get { return m_linksetRoot; } } + + private BSScene m_scene; + + private List m_children; + + // We lock the diddling of linkset classes to prevent any badness. + // This locks the modification of the instances of this class. Changes + // to the physical representation is done via the tainting mechenism. + private object m_linksetActivityLock = new Object(); + + // We keep the prim's mass in the linkset structure since it could be dependent on other prims + private float m_mass; + public float Mass + { + get + { + m_mass = ComputeLinksetMass(); + return m_mass; + } + } + + public OMV.Vector3 CenterOfMass + { + get { return ComputeLinksetCenterOfMass(); } + } + + public OMV.Vector3 GeometricCenter + { + get { return ComputeLinksetGeometricCenter(); } + } + + public BSLinkset(BSScene scene, BSPrim parent) + { + // A simple linkset of one (no children) + m_scene = scene; + m_linksetRoot = parent; + m_children = new List(); + m_mass = parent.MassRaw; + } + + // Link to a linkset where the child knows the parent. + // Parent changing should not happen so do some sanity checking. + // We return the parent's linkset so the child can track it's membership. + public BSLinkset AddMeToLinkset(BSPrim child, BSPrim parent) + { + lock (m_linksetActivityLock) + { + parent.Linkset.AddChildToLinkset(child); + } + return parent.Linkset; + } + + public BSLinkset RemoveMeFromLinkset(BSPrim child) + { + lock (m_linksetActivityLock) + { + if (IsRoot(child)) + { + // if root of linkset, take the linkset apart + while (m_children.Count > 0) + { + // Note that we don't do a foreach because the remove routine + // takes it out of the list. + RemoveChildFromLinkset(m_children[0]); + } + m_children.Clear(); // just to make sure + } + else + { + // Just removing a child from an existing linkset + RemoveChildFromLinkset(child); + } + } + + // The child is down to a linkset of just itself + return new BSLinkset(m_scene, child); + } + + // An existing linkset had one of its members rebuilt or something. + // Undo all the physical linking and rebuild the physical linkset. + public bool RefreshLinkset(BSPrim requestor) + { + return true; + } + + + // Return 'true' if the passed object is the root object of this linkset + public bool IsRoot(BSPrim requestor) + { + return (requestor.LocalID == m_linksetRoot.LocalID); + } + + // Return 'true' if this linkset has any children (more than the root member) + public bool HasAnyChildren { get { return (m_children.Count > 0); } } + + // Return 'true' if this child is in this linkset + public bool HasChild(BSPrim child) + { + bool ret = false; + foreach (BSPrim bp in m_children) + { + if (child.LocalID == bp.LocalID) + { + ret = true; + break; + } + } + return ret; + } + + private float ComputeLinksetMass() + { + float mass = m_linksetRoot.Mass; + foreach (BSPrim bp in m_children) + { + mass += bp.Mass; + } + return mass; + } + + private OMV.Vector3 ComputeLinksetCenterOfMass() + { + OMV.Vector3 com = m_linksetRoot.Position * m_linksetRoot.MassRaw; + float totalMass = m_linksetRoot.MassRaw; + + foreach (BSPrim bp in m_children) + { + com += bp.Position * bp.MassRaw; + totalMass += bp.MassRaw; + } + com /= totalMass; + + return com; + } + + private OMV.Vector3 ComputeLinksetGeometricCenter() + { + OMV.Vector3 com = m_linksetRoot.Position; + + foreach (BSPrim bp in m_children) + { + com += bp.Position * bp.MassRaw; + } + com /= m_children.Count + 1; + + return com; + } + + // I am the root of a linkset and a new child is being added + public void AddChildToLinkset(BSPrim pchild) + { + BSPrim child = pchild; + if (!HasChild(child)) + { + m_children.Add(child); + + m_scene.TaintedObject(delegate() + { + DebugLog("{0}: AddChildToLinkset: adding child {1} to {2}", LogHeader, child.LocalID, m_linksetRoot.LocalID); + DetailLog("{0},AddChildToLinkset,child={1}", m_linksetRoot.LocalID, pchild.LocalID); + PhysicallyLinkAChildToRoot(pchild); // build the physical binding between me and the child + }); + } + return; + } + + // I am the root of a linkset and one of my children is being removed. + // Safe to call even if the child is not really in my linkset. + public void RemoveChildFromLinkset(BSPrim pchild) + { + BSPrim child = pchild; + + if (m_children.Remove(child)) + { + m_scene.TaintedObject(delegate() + { + DebugLog("{0}: RemoveChildFromLinkset: Removing constraint to {1}", LogHeader, child.LocalID); + DetailLog("{0},RemoveChildFromLinkset,child={1}", m_linksetRoot.LocalID, pchild.LocalID); + + if (m_children.Count == 0) + { + // if the linkset is empty, make sure all linkages have been removed + PhysicallyUnlinkAllChildrenFromRoot(); + } + else + { + PhysicallyUnlinkAChildFromRoot(pchild); + } + }); + } + else + { + // This will happen if we remove the root of the linkset first. Non-fatal occurance. + // m_scene.Logger.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset", LogHeader); + } + return; + } + + // Create a constraint between me (root of linkset) and the passed prim (the child). + // Called at taint time! + private void PhysicallyLinkAChildToRoot(BSPrim childPrim) + { + // Zero motion for children so they don't interpolate + childPrim.ZeroMotion(); + + // relative position normalized to the root prim + OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(m_linksetRoot.Orientation); + OMV.Vector3 childRelativePosition = (childPrim.Position - m_linksetRoot.Position) * invThisOrientation; + + // relative rotation of the child to the parent + OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation; + + // create a constraint that allows no freedom of movement between the two objects + // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 + // DebugLog("{0}: CreateLinkset: Adding a constraint between root prim {1} and child prim {2}", LogHeader, LocalID, childPrim.LocalID); + DetailLog("{0},LinkAChildToMe,taint,root={1},child={2}", m_linksetRoot.LocalID, m_linksetRoot.LocalID, childPrim.LocalID); + BSConstraint constrain = m_scene.Constraints.CreateConstraint( + m_scene.World, m_linksetRoot.Body, childPrim.Body, + childRelativePosition, + childRelativeRotation, + OMV.Vector3.Zero, + OMV.Quaternion.Identity); + constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); + constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); + + // tweek the constraint to increase stability + constrain.UseFrameOffset(m_scene.BoolNumeric(m_scene.Params.linkConstraintUseFrameOffset)); + constrain.TranslationalLimitMotor(m_scene.BoolNumeric(m_scene.Params.linkConstraintEnableTransMotor), + m_scene.Params.linkConstraintTransMotorMaxVel, + m_scene.Params.linkConstraintTransMotorMaxForce); + + } + + // Remove linkage between myself and a particular child + // Called at taint time! + private void PhysicallyUnlinkAChildFromRoot(BSPrim childPrim) + { + DebugLog("{0}: PhysicallyUnlinkAChildFromRoot: RemoveConstraint between root prim {1} and child prim {2}", + LogHeader, m_linksetRoot.LocalID, childPrim.LocalID); + DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},child={2}", m_linksetRoot.LocalID, m_linksetRoot.LocalID, childPrim.LocalID); + // BulletSimAPI.RemoveConstraint(_scene.WorldID, LocalID, childPrim.LocalID); + m_scene.Constraints.RemoveAndDestroyConstraint(m_linksetRoot.Body, childPrim.Body); + } + + // Remove linkage between myself and any possible children I might have + // Called at taint time! + private void PhysicallyUnlinkAllChildrenFromRoot() + { + // DebugLog("{0}: PhysicallyUnlinkAllChildren:", LogHeader); + DetailLog("{0},PhysicallyUnlinkAllChildren,taint", m_linksetRoot.LocalID); + m_scene.Constraints.RemoveAndDestroyConstraint(m_linksetRoot.Body); + // BulletSimAPI.RemoveConstraintByID(_scene.WorldID, LocalID); + } + + // Invoke the detailed logger and output something if it's enabled. + private void DebugLog(string msg, params Object[] args) + { + m_scene.Logger.DebugFormat(msg, args); + } + + // Invoke the detailed logger and output something if it's enabled. + private void DetailLog(string msg, params Object[] args) + { + m_scene.PhysicsLogging.Write(msg, args); + } + +} +} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 3be28e3..d604f9c 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -66,7 +66,7 @@ public sealed class BSPrim : PhysicsActor private bool _isSelected; private bool _isVolumeDetect; private OMV.Vector3 _position; - private float _mass; + private float _mass; // the mass of this object private float _density; private OMV.Vector3 _force; private OMV.Vector3 _velocity; @@ -89,8 +89,13 @@ public sealed class BSPrim : PhysicsActor private bool _kinematic; private float _buoyancy; - private BSPrim _parentPrim; - private List _childrenPrims; + // Membership in a linkset is controlled by this class. + private BSLinkset _linkset; + public BSLinkset Linkset + { + get { return _linkset; } + set { _linkset = value; } + } private int _subscribedEventsMs = 0; private int _nextCollisionOkTime = 0; @@ -133,9 +138,8 @@ public sealed class BSPrim : PhysicsActor _friction = _scene.Params.defaultFriction; // TODO: compute based on object material _density = _scene.Params.defaultDensity; // TODO: compute based on object material _restitution = _scene.Params.defaultRestitution; - _parentPrim = null; // not a child or a parent + _linkset = new BSLinkset(_scene, this); // a linkset of one _vehicle = new BSDynamics(this); // add vehicleness - _childrenPrims = new List(); _mass = CalculateMass(); // do the actual object creation at taint time _scene.TaintedObject(delegate() @@ -161,16 +165,8 @@ public sealed class BSPrim : PhysicsActor _scene.TaintedObject(delegate() { - // undo any dependance with/on other objects - if (_parentPrim != null) - { - // If I'm someone's child, tell them to forget about me. - _parentPrim.RemoveChildFromLinkset(this); - _parentPrim = null; - } - - // make sure there are no other prims linked to me - UnlinkAllChildren(); + // Undo any links between me and any other object + _linkset = _linkset.RemoveMeFromLinkset(this); // everything in the C# world will get garbage collected. Tell the C++ world to free stuff. BulletSimAPI.DestroyObject(_scene.WorldID, LocalID); @@ -187,7 +183,7 @@ public sealed class BSPrim : PhysicsActor _scene.TaintedObject(delegate() { _mass = CalculateMass(); // changing size changes the mass - BulletSimAPI.SetObjectScaleMass(_scene.WorldID, _localID, _scale, Mass, IsPhysical); + BulletSimAPI.SetObjectScaleMass(_scene.WorldID, _localID, _scale, (IsPhysical ? _mass : 0f), IsPhysical); RecreateGeomAndObject(); }); } @@ -226,32 +222,8 @@ public sealed class BSPrim : PhysicsActor BSPrim parent = obj as BSPrim; DebugLog("{0}: link {1}/{2} to {3}", LogHeader, _avName, _localID, obj.LocalID); DetailLog("{0},link,parent={1}", LocalID, obj.LocalID); - // TODO: decide if this parent checking needs to happen at taint time - if (_parentPrim == null) - { - if (parent != null) - { - // I don't have a parent so I am joining a linkset - parent.AddChildToLinkset(this); - } - } - else - { - // I already have a parent, is parenting changing? - if (parent != _parentPrim) - { - if (parent == null) - { - // we are being removed from a linkset - _parentPrim.RemoveChildFromLinkset(this); - } - else - { - // asking to reparent a prim should not happen - m_log.ErrorFormat("{0}: link(): Reparenting a prim. ", LogHeader); - } - } - } + + _linkset = _linkset.AddMeToLinkset(this, parent); return; } @@ -260,81 +232,18 @@ public sealed class BSPrim : PhysicsActor // TODO: decide if this parent checking needs to happen at taint time // Race condition here: if link() and delink() in same simulation tick, the delink will not happen DebugLog("{0}: delink {1}/{2}. Parent={3}", LogHeader, _avName, _localID, - (_parentPrim==null ? "NULL" : _parentPrim._avName+"/"+_parentPrim.LocalID.ToString())); - DetailLog("{0},delink,parent={1}", LocalID, (_parentPrim==null ? "NULL" : _parentPrim.LocalID.ToString())); - if (_parentPrim != null) - { - _parentPrim.RemoveChildFromLinkset(this); - } - return; - } + _linkset.Root._avName+"/"+_linkset.Root.LocalID.ToString()); + DetailLog("{0},delink,parent={1}", LocalID, _linkset.Root.LocalID.ToString()); - // I am the root of a linkset and a new child is being added - public void AddChildToLinkset(BSPrim pchild) - { - BSPrim child = pchild; - _scene.TaintedObject(delegate() - { - if (!_childrenPrims.Contains(child)) - { - DebugLog("{0}: AddChildToLinkset: adding child {1} to {2}", LogHeader, child.LocalID, this.LocalID); - DetailLog("{0},AddChildToLinkset,child={1}", LocalID, pchild.LocalID); - _childrenPrims.Add(child); - child._parentPrim = this; // the child has gained a parent - // RecreateGeomAndObject(); // rebuild my shape with the new child added - LinkAChildToMe(pchild); // build the physical binding between me and the child - - _mass = CalculateMass(); - } - }); - return; - } - - // I am the root of a linkset and one of my children is being removed. - // Safe to call even if the child is not really in my linkset. - public void RemoveChildFromLinkset(BSPrim pchild) - { - BSPrim child = pchild; - _scene.TaintedObject(delegate() - { - if (_childrenPrims.Contains(child)) - { - DebugLog("{0}: RemoveChildFromLinkset: Removing constraint to {1}", LogHeader, child.LocalID); - DetailLog("{0},RemoveChildFromLinkset,child={1}", LocalID, pchild.LocalID); - _childrenPrims.Remove(child); - child._parentPrim = null; // the child has lost its parent - if (_childrenPrims.Count == 0) - { - // if the linkset is empty, make sure all linkages have been removed - UnlinkAllChildren(); - } - else - { - // RecreateGeomAndObject(); // rebuild my shape with the child removed - UnlinkAChildFromMe(pchild); - } - - _mass = CalculateMass(); - } - else - { - m_log.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset"); - } - }); - return; - } - - // return true if we are the root of a linkset (there are children to manage) - public bool IsRootOfLinkset - { - get { return (_parentPrim == null && _childrenPrims.Count != 0); } + _linkset.RemoveMeFromLinkset(this); + return; } // Set motion values to zero. // Do it to the properties so the values get set in the physics engine. // Push the setting of the values to the viewer. // Called at taint time! - private void ZeroMotion() + public void ZeroMotion() { _velocity = OMV.Vector3.Zero; _acceleration = OMV.Vector3.Zero; @@ -355,9 +264,10 @@ public sealed class BSPrim : PhysicsActor public override OMV.Vector3 Position { get { - // child prims move around based on their parent. Need to get the latest location - if (_parentPrim != null) + if (!_linkset.IsRoot(this)) + // child prims move around based on their parent. Need to get the latest location _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); + // don't do the GetObjectPosition for root elements because this function is called a zillion times // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); return _position; @@ -373,16 +283,31 @@ public sealed class BSPrim : PhysicsActor } } - // Return the effective mass of the object. Non-physical objects do not have mass. - public override float Mass { - get { - if (IsPhysical) - return _mass; - else - return 0f; + // Return the effective mass of the object. + // If there are multiple items in the linkset, add them together for the root + public override float Mass + { + get + { + return _linkset.Mass; } } + // used when we only want this prim's mass and not the linkset thing + public float MassRaw { get { return _mass; } } + + // Is this used? + public override OMV.Vector3 CenterOfMass + { + get { return _linkset.CenterOfMass; } + } + + // Is this used? + public override OMV.Vector3 GeometricCenter + { + get { return _linkset.GeometricCenter; } + } + public override OMV.Vector3 Force { get { return _force; } set { @@ -473,8 +398,6 @@ public sealed class BSPrim : PhysicsActor return; } - public override OMV.Vector3 GeometricCenter { get { return OMV.Vector3.Zero; } } - public override OMV.Vector3 CenterOfMass { get { return OMV.Vector3.Zero; } } public override OMV.Vector3 Velocity { get { return _velocity; } set { @@ -503,9 +426,9 @@ public sealed class BSPrim : PhysicsActor } public override OMV.Quaternion Orientation { get { - if (_parentPrim != null) + if (!_linkset.IsRoot(this)) { - // children move around because tied to parent. Get a fresh value. + // Children move around because tied to parent. Get a fresh value. _orientation = BulletSimAPI.GetObjectOrientation(_scene.WorldID, LocalID); } return _orientation; @@ -555,14 +478,16 @@ public sealed class BSPrim : PhysicsActor private void SetObjectDynamic() { // m_log.DebugFormat("{0}: ID={1}, SetObjectDynamic: IsStatic={2}, IsSolid={3}", LogHeader, _localID, IsStatic, IsSolid); - // non-physical things work best with a mass of zero - if (!IsStatic) - { - _mass = CalculateMass(); - RecreateGeomAndObject(); - } - DetailLog("{0},SetObjectDynamic,taint,static={1},solid={2},mass={3}", LocalID, IsStatic, IsSolid, Mass); - BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), Mass); + + RecreateGeomAndObject(); + + float mass = _mass; + // Bullet wants static objects have a mass of zero + if (IsStatic) + mass = 0f; + + DetailLog("{0},SetObjectDynamic,taint,static={1},solid={2},mass={3}", LocalID, IsStatic, IsSolid, mass); + BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass); } // prims don't fly @@ -1004,6 +929,9 @@ public sealed class BSPrim : PhysicsActor returnMass = _density * volume; + /* + * This change means each object keeps its own mass and the Mass property + * will return the sum if we're part of a linkset. if (IsRootOfLinkset) { foreach (BSPrim prim in _childrenPrims) @@ -1011,6 +939,7 @@ public sealed class BSPrim : PhysicsActor returnMass += prim.CalculateMass(); } } + */ if (returnMass <= 0) returnMass = 0.0001f; @@ -1026,9 +955,11 @@ public sealed class BSPrim : PhysicsActor // The objects needs a hull if it's physical otherwise a mesh is enough // No locking here because this is done when we know physics is not simulating // if 'forceRebuild' is true, the geometry is rebuilt. Otherwise a previously built version is used - private void CreateGeom(bool forceRebuild) + // Returns 'true' if the geometry was rebuilt + private bool CreateGeom(bool forceRebuild) { // the mesher thought this was too simple to mesh. Use a native Bullet collision shape. + bool ret = false; if (!_scene.NeedsMeshing(_pbs)) { if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1) @@ -1036,18 +967,26 @@ public sealed class BSPrim : PhysicsActor if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z) { // m_log.DebugFormat("{0}: CreateGeom: Defaulting to sphere of size {1}", LogHeader, _size); - _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE; - DetailLog("{0},CreateGeom,sphere", LocalID); - // Bullet native objects are scaled by the Bullet engine so pass the size in - _scale = _size; + if (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE) + { + DetailLog("{0},CreateGeom,sphere", LocalID); + _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE; + ret = true; + // Bullet native objects are scaled by the Bullet engine so pass the size in + _scale = _size; + } } } else { // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, size={2}", LogHeader, LocalID, _size); - DetailLog("{0},CreateGeom,box", LocalID); - _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX; - _scale = _size; + if (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX) + { + DetailLog("{0},CreateGeom,box", LocalID); + _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX; + ret = true; + _scale = _size; + } } } else @@ -1059,6 +998,7 @@ public sealed class BSPrim : PhysicsActor // physical objects require a hull for interaction. // This will create the mesh if it doesn't already exist CreateGeomHull(); + ret = true; } } else @@ -1067,9 +1007,11 @@ public sealed class BSPrim : PhysicsActor { // Static (non-physical) objects only need a mesh for bumping into CreateGeomMesh(); + ret = true; } } } + return ret; } // No locking here because this is done when we know physics is not simulating @@ -1254,20 +1196,18 @@ public sealed class BSPrim : PhysicsActor // No locking here because this is done when the physics engine is not simulating private void CreateObject() { - if (IsRootOfLinkset) - { - // Create a linkset around this object - CreateLinkset(); - } - else - { - // simple object - // the mesh or hull must have already been created in Bullet - ShapeData shape; - FillShapeInfo(out shape); - // m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, _localID, shape.Type); - BulletSimAPI.CreateObject(_scene.WorldID, shape); - } + // this routine is called when objects are rebuilt. + + // the mesh or hull must have already been created in Bullet + ShapeData shape; + FillShapeInfo(out shape); + // m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, _localID, shape.Type); + BulletSimAPI.CreateObject(_scene.WorldID, shape); + // the CreateObject() may have recreated the rigid body. Make sure we have the latest. + m_body.Ptr = BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID); + + // The root object could have been recreated. Make sure everything linksety is up to date. + _linkset.RefreshLinkset(this); } // Copy prim's info into the BulletSim shape description structure @@ -1279,7 +1219,7 @@ public sealed class BSPrim : PhysicsActor shape.Rotation = _orientation; shape.Velocity = _velocity; shape.Scale = _scale; - shape.Mass = Mass; + shape.Mass = _isPhysical ? _mass : 0f; shape.Buoyancy = _buoyancy; shape.HullKey = _hullKey; shape.MeshKey = _meshKey; @@ -1289,83 +1229,6 @@ public sealed class BSPrim : PhysicsActor shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue; } - #region Linkset creation and destruction - - // Create the linkset by putting constraints between the objects of the set so they cannot move - // relative to each other. - void CreateLinkset() - { - // DebugLog("{0}: CreateLinkset. Root prim={1}, prims={2}", LogHeader, LocalID, _childrenPrims.Count+1); - - // remove any constraints that might be in place - UnlinkAllChildren(); - - // create constraints between the root prim and each of the children - foreach (BSPrim prim in _childrenPrims) - { - LinkAChildToMe(prim); - } - } - - // Create a constraint between me (root of linkset) and the passed prim (the child). - // Called at taint time! - private void LinkAChildToMe(BSPrim childPrim) - { - // Zero motion for children so they don't interpolate - childPrim.ZeroMotion(); - - // relative position normalized to the root prim - OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(this._orientation); - OMV.Vector3 childRelativePosition = (childPrim._position - this._position) * invThisOrientation; - - // relative rotation of the child to the parent - OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim._orientation; - - // create a constraint that allows no freedom of movement between the two objects - // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 - // DebugLog("{0}: CreateLinkset: Adding a constraint between root prim {1} and child prim {2}", LogHeader, LocalID, childPrim.LocalID); - DetailLog("{0},LinkAChildToMe,taint,root={1},child={2}", LocalID, LocalID, childPrim.LocalID); - BSConstraint constrain = _scene.Constraints.CreateConstraint( - _scene.World, this.Body, childPrim.Body, - childRelativePosition, - childRelativeRotation, - OMV.Vector3.Zero, - OMV.Quaternion.Identity); - constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); - constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); - - // tweek the constraint to increase stability - constrain.UseFrameOffset(_scene.BoolNumeric(_scene.Params.linkConstraintUseFrameOffset)); - if (_scene.BoolNumeric(_scene.Params.linkConstraintEnableTransMotor)) - { - constrain.TranslationalLimitMotor(true, - _scene.Params.linkConstraintTransMotorMaxVel, - _scene.Params.linkConstraintTransMotorMaxForce); - } - } - - // Remove linkage between myself and a particular child - // Called at taint time! - private void UnlinkAChildFromMe(BSPrim childPrim) - { - DebugLog("{0}: UnlinkAChildFromMe: RemoveConstraint between root prim {1} and child prim {2}", - LogHeader, LocalID, childPrim.LocalID); - DetailLog("{0},UnlinkAChildFromMe,taint,root={1},child={2}", LocalID, LocalID, childPrim.LocalID); - // BulletSimAPI.RemoveConstraint(_scene.WorldID, LocalID, childPrim.LocalID); - _scene.Constraints.RemoveAndDestroyConstraint(this.Body, childPrim.Body); - } - - // Remove linkage between myself and any possible children I might have - // Called at taint time! - private void UnlinkAllChildren() - { - DebugLog("{0}: UnlinkAllChildren:", LogHeader); - DetailLog("{0},UnlinkAllChildren,taint", LocalID); - _scene.Constraints.RemoveAndDestroyConstraint(this.Body); - // BulletSimAPI.RemoveConstraintByID(_scene.WorldID, LocalID); - } - - #endregion // Linkset creation and destruction // Rebuild the geometry and object. // This is called when the shape changes so we need to recreate the mesh/hull. @@ -1443,7 +1306,7 @@ public sealed class BSPrim : PhysicsActor // Don't check for damping here -- it's done in BulletSim and SceneObjectPart. // Updates only for individual prims and for the root object of a linkset. - if (_parentPrim == null) + if (_linkset.IsRoot(this)) { // Assign to the local variables so the normal set action does not happen _position = entprop.Position; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index a1587a8..c6d622b 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -73,7 +73,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); private static readonly string LogHeader = "[BULLETS SCENE]"; - private void DebugLog(string mm, params Object[] xx) { if (shouldDebugLog) m_log.DebugFormat(mm, xx); } + public void DebugLog(string mm, params Object[] xx) { if (shouldDebugLog) m_log.DebugFormat(mm, xx); } public string BulletSimVersion = "?"; @@ -87,6 +87,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters private uint m_worldID; public uint WorldID { get { return m_worldID; } } + // let my minuions use my logger + public ILog Logger { get { return m_log; } } + private bool m_initialized = false; private int m_detailedStatsStep = 0; @@ -1026,7 +1029,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters (s,p,l,v) => { s.m_params[0].numberOfSolverIterations = v; } ), new ParameterDefn("LinkConstraintUseFrameOffset", "For linksets built with constraints, enable frame offsetFor linksets built with constraints, enable frame offset.", - ConfigurationParameters.numericTrue, + ConfigurationParameters.numericFalse, (s,cf,p,v) => { s.m_params[0].linkConstraintUseFrameOffset = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, (s) => { return s.m_params[0].linkConstraintUseFrameOffset; }, (s,p,l,v) => { s.m_params[0].linkConstraintUseFrameOffset = v; } ), diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 89fd9b7..65e3145 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -239,10 +239,10 @@ public static extern bool DestroyMesh(uint worldID, System.UInt64 meshKey); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern bool CreateObject(uint worldID, ShapeData shapeData); +/* Remove old functionality [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern void CreateLinkset(uint worldID, int objectCount, ShapeData[] shapeDatas); -/* Remove old functionality [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern void AddConstraint(uint worldID, uint id1, uint id2, Vector3 frame1, Quaternion frame1rot, -- cgit v1.1 From ce812c88ccc9226167b049e49296892943409e3f Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Thu, 26 Jul 2012 15:24:53 -0700 Subject: BulletSim: fix a recursive loop when fetching the mass of the root of a linkset. --- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 6 +++--- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index a1027ee..3bc2100 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -50,7 +50,7 @@ public class BSLinkset // We keep the prim's mass in the linkset structure since it could be dependent on other prims private float m_mass; - public float Mass + public float LinksetMass { get { @@ -150,10 +150,10 @@ public class BSLinkset private float ComputeLinksetMass() { - float mass = m_linksetRoot.Mass; + float mass = m_linksetRoot.MassRaw; foreach (BSPrim bp in m_children) { - mass += bp.Mass; + mass += bp.MassRaw; } return mass; } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index d604f9c..7590d93 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -289,7 +289,7 @@ public sealed class BSPrim : PhysicsActor { get { - return _linkset.Mass; + return _linkset.LinksetMass; } } -- cgit v1.1 From 21b1fec32d33ac00677e25ca00463a76794e1a62 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 27 Jul 2012 00:28:23 +0100 Subject: Fix issue where RegionCombinerModule was not removing regions from its dictionary on RemoveRegion(), causing a later issue if regions were restarted (removed then readded). --- OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'OpenSim') diff --git a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs index 204c4ff..3144d76 100644 --- a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs +++ b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs @@ -99,6 +99,8 @@ namespace OpenSim.Region.RegionCombinerModule public void RemoveRegion(Scene scene) { + lock (m_startingScenes) + m_startingScenes.Remove(scene.RegionInfo.originRegionID); } public void RegionLoaded(Scene scene) -- cgit v1.1 From 1133f81dce840e394763a4eea03067fa8d18f0e1 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 27 Jul 2012 20:40:25 +0100 Subject: Remove a couple of compiler warnings pointed out by SignpostMarv --- OpenSim/Framework/Servers/BaseOpenSimServer.cs | 1 - OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs | 2 -- 2 files changed, 3 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Framework/Servers/BaseOpenSimServer.cs b/OpenSim/Framework/Servers/BaseOpenSimServer.cs index 2a8ae38..7a5c16d 100644 --- a/OpenSim/Framework/Servers/BaseOpenSimServer.cs +++ b/OpenSim/Framework/Servers/BaseOpenSimServer.cs @@ -43,7 +43,6 @@ using OpenSim.Framework.Console; using OpenSim.Framework.Monitoring; using OpenSim.Framework.Servers; using OpenSim.Framework.Servers.HttpServer; -using OpenSim.Framework.Monitoring; using Timer=System.Timers.Timer; using OpenMetaverse; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index e0b4db6..faad75d 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -3242,8 +3242,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api ((LSL_Api)m_LSL_Api).llSay(0, string.Format("Unable to attach, item '{0}' is not an object.", itemName)); throw new Exception(String.Format("The inventory item '{0}' is not an object", itemName)); - - return; } ScenePresence sp = World.GetScenePresence(avatarId); -- cgit v1.1 From 0d9afad3fecd13b06065af556ed9a01f8a745f44 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 27 Jul 2012 22:15:25 +0100 Subject: Remove duplicated IScenePresence.PresenceType. This is already in ISceneAgent.PresenceType from which IScenePresence inherits. No other code changes required. --- OpenSim/Region/Framework/Interfaces/IScenePresence.cs | 2 -- 1 file changed, 2 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Framework/Interfaces/IScenePresence.cs b/OpenSim/Region/Framework/Interfaces/IScenePresence.cs index 3f68ee0..0fe681f 100644 --- a/OpenSim/Region/Framework/Interfaces/IScenePresence.cs +++ b/OpenSim/Region/Framework/Interfaces/IScenePresence.cs @@ -40,8 +40,6 @@ namespace OpenSim.Region.Framework.Interfaces /// public interface IScenePresence : ISceneAgent { - PresenceType PresenceType { get; } - /// /// Copy of the script states while the agent is in transit. This state may /// need to be placed back in case of transfer fail. -- cgit v1.1 From f3c5ce1bbd86fafa0e436efe5de804b65d64b8af Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 27 Jul 2012 22:20:08 +0100 Subject: minor: Comment out unused MemoryWatchdog.m_churnRatePerMillisecond - this is currently calculated dynamically --- OpenSim/Framework/Monitoring/MemoryWatchdog.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim') diff --git a/OpenSim/Framework/Monitoring/MemoryWatchdog.cs b/OpenSim/Framework/Monitoring/MemoryWatchdog.cs index 6599613..a23cf1f 100644 --- a/OpenSim/Framework/Monitoring/MemoryWatchdog.cs +++ b/OpenSim/Framework/Monitoring/MemoryWatchdog.cs @@ -89,7 +89,7 @@ namespace OpenSim.Framework.Monitoring /// /// Memory churn rate per millisecond. /// - private static double m_churnRatePerMillisecond; +// private static double m_churnRatePerMillisecond; /// /// Historical samples for calculating moving average. -- cgit v1.1 From d4f476c7ce341e47bab734e4f4caaa57c1bbeff0 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 27 Jul 2012 23:31:19 +0100 Subject: Remove the LandGeom checks in OdeScene - these are pointless since LandGeom is always IntPtr.Zero and contacts returned always have a valid geometry. Possibly this was for a feature that was never implemented or was otherwise removed. Thanks to SignpostMarv for the spot of the warning that shows this parameter was never changed. --- OpenSim/Region/Physics/OdePlugin/OdeScene.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs index 0db936f..929b019 100644 --- a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs +++ b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs @@ -290,7 +290,6 @@ namespace OpenSim.Region.Physics.OdePlugin private readonly IntPtr contactgroup; - internal IntPtr LandGeom; internal IntPtr WaterGeom; private float nmTerrainContactFriction = 255.0f; @@ -1512,8 +1511,7 @@ namespace OpenSim.Region.Physics.OdePlugin { if (((Math.Abs(contactGeom.normal.X - contact.normal.X) < 1.026f) && (Math.Abs(contactGeom.normal.Y - contact.normal.Y) < 0.303f) - && (Math.Abs(contactGeom.normal.Z - contact.normal.Z) < 0.065f)) - && contactGeom.g1 != LandGeom && contactGeom.g2 != LandGeom) + && (Math.Abs(contactGeom.normal.Z - contact.normal.Z) < 0.065f))) { if (Math.Abs(contact.depth - contactGeom.depth) < 0.052f) { @@ -1542,7 +1540,7 @@ namespace OpenSim.Region.Physics.OdePlugin //d.GeomGetAABB(contactGeom.g2, out aabb2); //d.GeomGetAABB(contactGeom.g1, out aabb1); //aabb1. - if (((Math.Abs(contactGeom.normal.X - contact.normal.X) < 1.026f) && (Math.Abs(contactGeom.normal.Y - contact.normal.Y) < 0.303f) && (Math.Abs(contactGeom.normal.Z - contact.normal.Z) < 0.065f)) && contactGeom.g1 != LandGeom && contactGeom.g2 != LandGeom) + if (((Math.Abs(contactGeom.normal.X - contact.normal.X) < 1.026f) && (Math.Abs(contactGeom.normal.Y - contact.normal.Y) < 0.303f) && (Math.Abs(contactGeom.normal.Z - contact.normal.Z) < 0.065f))) { if (contactGeom.normal.X == contact.normal.X && contactGeom.normal.Y == contact.normal.Y && contactGeom.normal.Z == contact.normal.Z) { -- cgit v1.1 From adbdb220df4aacc93e81eeb2eb1854825e4db7fb Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Fri, 27 Jul 2012 22:15:25 +0100 Subject: making first run more resilient to bad input (loop until good input, rather than crash) --- OpenSim/Framework/RegionInfo.cs | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Framework/RegionInfo.cs b/OpenSim/Framework/RegionInfo.cs index a505524..2080a16 100644 --- a/OpenSim/Framework/RegionInfo.cs +++ b/OpenSim/Framework/RegionInfo.cs @@ -480,9 +480,16 @@ namespace OpenSim.Framework MainConsole.Instance.Output("=====================================\n"); if (name == String.Empty) - name = MainConsole.Instance.CmdPrompt("New region name", name); - if (name == String.Empty) - throw new Exception("Cannot interactively create region with no name"); + { + while (name.Trim() == string.Empty) + { + name = MainConsole.Instance.CmdPrompt("New region name", name); + if (name.Trim() == string.Empty) + { + MainConsole.Instance.Output("Cannot interactively create region with no name"); + } + } + } source.AddConfig(name); @@ -513,15 +520,20 @@ namespace OpenSim.Framework // allKeys.Remove("RegionUUID"); string regionUUID = config.GetString("RegionUUID", string.Empty); - if (regionUUID == String.Empty) + if (!UUID.TryParse(regionUUID.Trim(), out RegionID)) { UUID newID = UUID.Random(); - - regionUUID = MainConsole.Instance.CmdPrompt("RegionUUID", newID.ToString()); + while (RegionID == UUID.Zero) + { + regionUUID = MainConsole.Instance.CmdPrompt("RegionUUID", newID.ToString()); + if (!UUID.TryParse(regionUUID.Trim(), out RegionID)) + { + MainConsole.Instance.Output("RegionUUID must be a valid UUID"); + } + } config.Set("RegionUUID", regionUUID); } - RegionID = new UUID(regionUUID); originRegionID = RegionID; // What IS this?! (Needed for RegionCombinerModule?) // Location -- cgit v1.1 From 7e89b99e6ad93a313338099f9033adafa26ee426 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 27 Jul 2012 23:58:53 +0100 Subject: Avoid a race condition between the scene shutdown thread and the update thread since commit c150320 (Thu Jul 26 15:27:18 2012) c150320 started explicitly disposing of the physics scene and nulling it out on region shutdown. However, the update loop may not have yet checked Scene.ShuttingDown, particularly if avatars were not in the scene, causing failure when it tried to lookup time dilation. This commit moves the setting of m_shuttingDown above the existing 500ms pause to notify avatars that they are being kicked. This should not affect the few other places that use this flag. --- OpenSim/Region/Framework/Scenes/Scene.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 1734704..eb4ba41 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1199,15 +1199,17 @@ namespace OpenSim.Region.Framework.Scenes avatar.ControllingClient.SendShutdownConnectionNotice(); }); + // Stop updating the scene objects and agents. + m_shuttingDown = true; + // Wait here, or the kick messages won't actually get to the agents before the scene terminates. + // We also need to wait to avoid a race condition with the scene update loop which might not yet + // have checked ShuttingDown. Thread.Sleep(500); // Stop all client threads. ForEachScenePresence(delegate(ScenePresence avatar) { avatar.ControllingClient.Close(); }); - // Stop updating the scene objects and agents. - m_shuttingDown = true; - m_log.Debug("[SCENE]: Persisting changed objects"); EventManager.TriggerSceneShuttingDown(this); -- cgit v1.1 From 72d29bdb40c16ba4785b16e4025bf810baa96cb5 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Fri, 27 Jul 2012 10:49:47 +0100 Subject: LSL/OSSL lacks Math.Min & Math.Max implementations. --- .../Shared/Api/Implementation/OSSL_Api.cs | 28 ++++++++++++++++++++++ .../ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs | 16 +++++++++++++ .../ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs | 10 ++++++++ 3 files changed, 54 insertions(+) (limited to 'OpenSim') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index faad75d..44de176 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -3286,5 +3286,33 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api UUID test; return UUID.TryParse(thing, out test) ? 1 : 0; } + + /// + /// Wraps to Math.Min() + /// + /// + /// + /// + public LSL_Float osMin(double a, double b) + { + CheckThreatLevel(ThreatLevel.None, "osMin"); + m_host.AddScriptLPS(1); + + return Math.Min(a, b); + } + + /// + /// Wraps to Math.max() + /// + /// + /// + /// + public LSL_Float osMax(double a, double b) + { + CheckThreatLevel(ThreatLevel.None, "osMax"); + m_host.AddScriptLPS(1); + + return Math.Max(a, b); + } } } \ No newline at end of file diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs index c9403eb..f73a85e 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs @@ -283,5 +283,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces /// /// 1 if thing is a valid UUID, 0 otherwise LSL_Integer osIsUUID(string thing); + + /// + /// Wraps to Math.Min() + /// + /// + /// + /// + LSL_Float osMin(double a, double b); + + /// + /// Wraps to Math.max() + /// + /// + /// + /// + LSL_Float osMax(double a, double b); } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs index 99995a7..53daa13 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs @@ -935,5 +935,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase { return m_OSSL_Functions.osIsUUID(thing); } + + public LSL_Float osMin(double a, double b) + { + return m_OSSL_Functions.osMin(a, b); + } + + public LSL_Float osMax(double a, double b) + { + return m_OSSL_Functions.osMax(a, b); + } } } -- cgit v1.1