From b6476eaac35c37862ae74e6f6a070a80cf51c0c0 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 17 Jul 2012 00:00:26 +0100 Subject: Stop sending the viewer an inventory create message if a known attachment item is updated. This doesn't seem to make any sense and probably stems from a period when this code was directly involved in attaching objects directly from the scene. This message is already being sent by InventoryAccessModule code instead. --- OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index 64ee7e4..fff47e2 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -566,11 +566,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments item.InvType = (int)InventoryType.Object; m_scene.InventoryService.UpdateItem(item); - - // this gets called when the agent logs off! - if (sp.ControllingClient != null) - sp.ControllingClient.SendInventoryItemCreateUpdate(item, 0); } + grp.HasGroupChanged = false; // Prevent it being saved over and over } // else -- cgit v1.1 From 356d5972961cc91593cfcc5c529a8ba81381b8f4 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 17 Jul 2012 00:17:51 +0100 Subject: Restore update of inventory item on derez/logout. This is necessary to update the name if this has been changed whilst attached. Note, this behaviour appears to be at variance with the ll grid as of Tues 17 July 2012, testing with viewer 3.2.1. The item name in inventory does not change either at the point of detach or after a relog. --- OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index fff47e2..d34a8f6 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -566,8 +566,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments item.InvType = (int)InventoryType.Object; m_scene.InventoryService.UpdateItem(item); + + // If the name of the object has been changed whilst attached then we want to update the inventory + // item in the viewer. + if (sp.ControllingClient != null) + sp.ControllingClient.SendInventoryItemCreateUpdate(item, 0); } - + grp.HasGroupChanged = false; // Prevent it being saved over and over } // else -- cgit v1.1 From c489bc1cd2c81273aaf0e0beb23b3714079ce4be Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 17 Jul 2012 15:00:42 +0200 Subject: Make the scrpt running flag work properly --- .../ScriptEngine/Shared/Instance/ScriptInstance.cs | 14 ++++++++------ OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | 16 ++++++++++++++++ 2 files changed, 24 insertions(+), 6 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs index d570ef7..5793cc9 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs @@ -312,11 +312,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance part.SetScriptEvents(ItemID, (int)m_Script.GetStateEventFlags(State)); - Running = false; - - if (ShuttingDown) + if (!Running) m_startOnInit = false; + Running = false; + // we get new rez events on sim restart, too // but if there is state, then we fire the change // event @@ -352,12 +352,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance public void Init() { - if (!m_startOnInit) + if (ShuttingDown) return; if (m_startedFromSavedState) { - Start(); + if (m_startOnInit) + Start(); if (m_postOnRez) { PostEvent(new EventParams("on_rez", @@ -389,7 +390,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance } else { - Start(); + if (m_startOnInit) + Start(); PostEvent(new EventParams("state_entry", new Object[0], new DetectParams[0])); if (m_postOnRez) diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index 01aebb6..7a9c80c 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -108,6 +108,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine private bool m_KillTimedOutScripts; private string m_ScriptEnginesPath = null; + private ExpiringCache m_runFlags = new ExpiringCache(); + /// /// Is the entire simulator in the process of shutting down? /// @@ -1196,6 +1198,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine if (instance != null) instance.Init(); + bool runIt; + if (m_runFlags.TryGetValue(itemID, out runIt)) + { + if (!runIt) + StopScript(itemID); + m_runFlags.Remove(itemID); + } + return true; } @@ -1568,6 +1578,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine IScriptInstance instance = GetInstance(itemID); if (instance != null) instance.Start(); + else + m_runFlags.AddOrUpdate(itemID, true, 240); } public void StopScript(UUID itemID) @@ -1579,6 +1591,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine // cause issues on mono 2.6, 2.10 and possibly later where locks are not released properly on abort. instance.Stop(1000); } + else + { + m_runFlags.AddOrUpdate(itemID, false, 240); + } } public DetectParams GetDetectParams(UUID itemID, int idx) -- cgit v1.1 From 59a29f5f221a1ffe4e22c63ef9da82270442b213 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 17 Jul 2012 22:56:21 +0100 Subject: Revert "refactor: make llGiveInventory() use existing GetInventoryItem() method rather than iterate through TaskInventory itself." This reverts commit 58b13d51a7eddb442e38e6dc6790a9e7cf68bad7. --- .../Shared/Api/Implementation/LSL_Api.cs | 35 +++++++++++++++------- 1 file changed, 24 insertions(+), 11 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index f88338d..c1ac0e5 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -3925,8 +3925,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llGiveInventory(string destination, string inventory) { m_host.AddScriptLPS(1); - + bool found = false; UUID destId = UUID.Zero; + UUID objId = UUID.Zero; + int assetType = 0; + string objName = String.Empty; if (!UUID.TryParse(destination, out destId)) { @@ -3934,16 +3937,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return; } - TaskInventoryItem item = m_host.Inventory.GetInventoryItem(inventory); + // move the first object found with this inventory name + lock (m_host.TaskInventory) + { + foreach (KeyValuePair inv in m_host.TaskInventory) + { + if (inv.Value.Name == inventory) + { + found = true; + objId = inv.Key; + assetType = inv.Value.Type; + objName = inv.Value.Name; + break; + } + } + } - if (item == null) + if (!found) { llSay(0, String.Format("Could not find object '{0}'", inventory)); throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory)); } - UUID objId = item.ItemID; - // check if destination is an object if (World.GetSceneObjectPart(destId) != null) { @@ -3974,23 +3989,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return; byte[] bucket = new byte[17]; - bucket[0] = (byte)item.Type; + bucket[0] = (byte)assetType; byte[] objBytes = agentItem.ID.GetBytes(); Array.Copy(objBytes, 0, bucket, 1, 16); GridInstantMessage msg = new GridInstantMessage(World, - m_host.UUID, m_host.Name + ", an object owned by " + - resolveName(m_host.OwnerID) + ",", destId, + m_host.UUID, m_host.Name+", an object owned by "+ + resolveName(m_host.OwnerID)+",", destId, (byte)InstantMessageDialog.TaskInventoryOffered, - false, item.Name + "\n" + m_host.Name + " is located at " + + false, objName+"\n"+m_host.Name+" is located at "+ World.RegionInfo.RegionName+" "+ m_host.AbsolutePosition.ToString(), agentItem.ID, true, m_host.AbsolutePosition, bucket); - if (m_TransferModule != null) m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); - ScriptSleep(3000); } } -- cgit v1.1 From ecb759c1e5b0ea3e1c81310acf3fe31561d2be3a Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 17 Jul 2012 23:31:38 +0100 Subject: Fix regression where llGiveInventory() had stopped asking non-owner receivers to accept/decline. This appears to be a regression from back in commit db91044 (Mon Aug 22 2011) where we started to send TaskInventoryOffered msg dialog rather than InventoryOffered dialog. This is probably correct, but failed because the bucket was too large and because we wouldn't have handled the TaskInventoryDeclined option anyway. This patch handles both of these and make llGiveInventoryList() use TaskInventoryOffered as well Fixes http://opensimulator.org/mantis/view.php?id=6089 --- .../Avatar/InstantMessage/MessageTransferModule.cs | 19 ++++--- .../Inventory/Transfer/InventoryTransferModule.cs | 4 +- .../Shared/Api/Implementation/LSL_Api.cs | 58 +++++++++++----------- 3 files changed, 43 insertions(+), 38 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs index 0dad3c4..596174b 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs @@ -137,13 +137,15 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage foreach (Scene scene in m_Scenes) { // m_log.DebugFormat( -// "[INSTANT MESSAGE]: Looking for root agent {0} in {1}", +// "[INSTANT MESSAGE]: Looking for root agent {0} in {1}", // toAgentID.ToString(), scene.RegionInfo.RegionName); + ScenePresence sp = scene.GetScenePresence(toAgentID); if (sp != null && !sp.IsChildAgent) { // Local message -// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", user.Name, toAgentID); + m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", sp.Name, toAgentID); + sp.ControllingClient.SendInstantMessage(im); // Message sent @@ -155,13 +157,15 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage // try child avatar second foreach (Scene scene in m_Scenes) { -// m_log.DebugFormat( -// "[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName); + m_log.DebugFormat( + "[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName); + ScenePresence sp = scene.GetScenePresence(toAgentID); if (sp != null) { // Local message -// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", user.Name, toAgentID); + m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", sp.Name, toAgentID); + sp.ControllingClient.SendInstantMessage(im); // Message sent @@ -170,10 +174,9 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage } } -// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID); - SendGridInstantMessageViaXMLRPC(im, result); + m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID); - return; + SendGridInstantMessageViaXMLRPC(im, result); } private void HandleUndeliveredMessage(GridInstantMessage im, MessageResultNotification result) diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs index 19c774f..f3af59a 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs @@ -297,7 +297,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer }); } } - else if (im.dialog == (byte) InstantMessageDialog.InventoryDeclined) + else if ( + im.dialog == (byte)InstantMessageDialog.InventoryDeclined + || im.dialog == (byte)InstantMessageDialog.TaskInventoryDeclined) { // Here, the recipient is local and we can assume that the // inventory is loaded. Courtesy of the above bulk update, diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index c1ac0e5..b43e8e7 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -3988,22 +3988,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (agentItem == null) return; - byte[] bucket = new byte[17]; - bucket[0] = (byte)assetType; - byte[] objBytes = agentItem.ID.GetBytes(); - Array.Copy(objBytes, 0, bucket, 1, 16); - - GridInstantMessage msg = new GridInstantMessage(World, - m_host.UUID, m_host.Name+", an object owned by "+ - resolveName(m_host.OwnerID)+",", destId, - (byte)InstantMessageDialog.TaskInventoryOffered, - false, objName+"\n"+m_host.Name+" is located at "+ - World.RegionInfo.RegionName+" "+ - m_host.AbsolutePosition.ToString(), - agentItem.ID, true, m_host.AbsolutePosition, - bucket); if (m_TransferModule != null) + { + byte[] bucket = new byte[] { (byte)assetType }; + + GridInstantMessage msg = new GridInstantMessage(World, + m_host.UUID, m_host.Name + ", an object owned by " + + resolveName(m_host.OwnerID) + ",", destId, + (byte)InstantMessageDialog.TaskInventoryOffered, + false, objName + "\n" + m_host.Name + " is located at " + + World.RegionInfo.RegionName + " " + + m_host.AbsolutePosition.ToString(), + agentItem.ID, true, m_host.AbsolutePosition, + bucket); + m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); + } + ScriptSleep(3000); } } @@ -6410,23 +6411,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (folderID == UUID.Zero) return; - byte[] bucket = new byte[17]; - bucket[0] = (byte)AssetType.Folder; - byte[] objBytes = folderID.GetBytes(); - Array.Copy(objBytes, 0, bucket, 1, 16); - - GridInstantMessage msg = new GridInstantMessage(World, - m_host.UUID, m_host.Name + ", an object owned by " + - resolveName(m_host.OwnerID) + ",", destID, - (byte)InstantMessageDialog.InventoryOffered, - false, category + "\n" + m_host.Name + " is located at " + - World.RegionInfo.RegionName + " " + - m_host.AbsolutePosition.ToString(), - folderID, true, m_host.AbsolutePosition, - bucket); - if (m_TransferModule != null) + { + byte[] bucket = new byte[] { (byte)AssetType.Folder }; + + GridInstantMessage msg = new GridInstantMessage(World, + m_host.UUID, m_host.Name + ", an object owned by " + + resolveName(m_host.OwnerID) + ",", destID, + (byte)InstantMessageDialog.TaskInventoryOffered, + false, category + "\n" + m_host.Name + " is located at " + + World.RegionInfo.RegionName + " " + + m_host.AbsolutePosition.ToString(), + folderID, true, m_host.AbsolutePosition, + bucket); + m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); + } } public void llSetVehicleType(int type) -- cgit v1.1 From 48a5f10be1a7e487690c1b4e7d220e26c53585c5 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 17 Jul 2012 23:48:09 +0100 Subject: Revert "Revert "refactor: make llGiveInventory() use existing GetInventoryItem() method rather than iterate through TaskInventory itself."" This reverts commit 59a29f5f221a1ffe4e22c63ef9da82270442b213. The original revert was committed by mistake - it turns out this was not the cause of Mantis 6089 Conflicts: OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs --- .../Shared/Api/Implementation/LSL_Api.cs | 33 ++++++---------------- 1 file changed, 9 insertions(+), 24 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index b43e8e7..084bd41 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -3925,11 +3925,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llGiveInventory(string destination, string inventory) { m_host.AddScriptLPS(1); - bool found = false; + UUID destId = UUID.Zero; - UUID objId = UUID.Zero; - int assetType = 0; - string objName = String.Empty; if (!UUID.TryParse(destination, out destId)) { @@ -3937,28 +3934,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return; } - // move the first object found with this inventory name - lock (m_host.TaskInventory) - { - foreach (KeyValuePair inv in m_host.TaskInventory) - { - if (inv.Value.Name == inventory) - { - found = true; - objId = inv.Key; - assetType = inv.Value.Type; - objName = inv.Value.Name; - break; - } - } - } + TaskInventoryItem item = m_host.Inventory.GetInventoryItem(inventory); - if (!found) + if (item == null) { llSay(0, String.Format("Could not find object '{0}'", inventory)); throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory)); } + UUID objId = item.ItemID; + // check if destination is an object if (World.GetSceneObjectPart(destId) != null) { @@ -3990,14 +3975,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (m_TransferModule != null) { - byte[] bucket = new byte[] { (byte)assetType }; - + byte[] bucket = new byte[] { (byte)item.Type }; + GridInstantMessage msg = new GridInstantMessage(World, m_host.UUID, m_host.Name + ", an object owned by " + resolveName(m_host.OwnerID) + ",", destId, (byte)InstantMessageDialog.TaskInventoryOffered, - false, objName + "\n" + m_host.Name + " is located at " + - World.RegionInfo.RegionName + " " + + false, item.Name + "\n" + m_host.Name + " is located at " + + World.RegionInfo.RegionName+" "+ m_host.AbsolutePosition.ToString(), agentItem.ID, true, m_host.AbsolutePosition, bucket); -- cgit v1.1 From eb590becf03d94d9afeef471c000c46b044d0c5b Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 18 Jul 2012 00:14:02 +0100 Subject: Close() the ScenePresence after we've removed it from the scene graph, to cut down race conditions when another thread manages the grab the presence after some SP structures have been reset. --- OpenSim/Region/Framework/Scenes/Scene.cs | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 3e9583c..de2b192 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -3317,24 +3317,30 @@ namespace OpenSim.Region.Framework.Scenes if (AgentTransactionsModule != null) AgentTransactionsModule.RemoveAgentAssetTransactions(agentID); - avatar.Close(); - m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode); } catch (Exception e) { m_log.Error( - string.Format("[SCENE]: Exception removing {0} from {1}, ", avatar.Name, RegionInfo.RegionName), e); + string.Format("[SCENE]: Exception removing {0} from {1}. Cleaning up. Exception ", avatar.Name, Name), e); } finally { - // Always clean these structures up so that any failure above doesn't cause them to remain in the - // scene with possibly bad effects (e.g. continually timing out on unacked packets and triggering - // the same cleanup exception continually. - // TODO: This should probably extend to the whole method, but we don't want to also catch the NRE - // since this would hide the underlying failure and other associated problems. - m_sceneGraph.RemoveScenePresence(agentID); - m_clientManager.Remove(agentID); + try + { + // Always clean these structures up so that any failure above doesn't cause them to remain in the + // scene with possibly bad effects (e.g. continually timing out on unacked packets and triggering + // the same cleanup exception continually. + m_sceneGraph.RemoveScenePresence(agentID); + m_clientManager.Remove(agentID); + + avatar.Close(); + } + catch (Exception e) + { + m_log.Error( + string.Format("[SCENE]: Exception in final clean up of {0} in {1}. Exception ", avatar.Name, Name), e); + } } //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false)); -- cgit v1.1 From cd6d7429f86eda4040cde664de4d690945d8be6b Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 18 Jul 2012 21:03:35 +0100 Subject: Only listen to LoginsEnabled event in RegionReadyModule if it has been asked to disable logins until all scripts have been compiled --- .../RegionReadyModule/RegionReadyModule.cs | 48 ++++++++++------------ 1 file changed, 22 insertions(+), 26 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs index 600cafb..aeab61c 100644 --- a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs @@ -56,7 +56,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady private bool m_lastOarLoadedOk; private int m_channelNotify = -1000; private bool m_enabled = false; - private bool m_disable_logins = false; + private bool m_disable_logins; private string m_uri = string.Empty; Scene m_scene = null; @@ -100,24 +100,23 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady m_scene.EventManager.OnOarFileLoaded += OnOarFileLoaded; m_scene.EventManager.OnRezScript += OnRezScript; - m_scene.EventManager.OnLoginsEnabled += OnLoginsEnabled; m_log.DebugFormat("[RegionReady]: Enabled for region {0}", scene.RegionInfo.RegionName); - if (m_disable_logins == true) + if (m_disable_logins) { + m_scene.EventManager.OnLoginsEnabled += OnLoginsEnabled; scene.LoginLock = true; - scene.LoginsDisabled = true; - m_log.InfoFormat("[RegionReady]: Region {0} - logins disabled during initialization.",m_scene.RegionInfo.RegionName); + m_log.InfoFormat("[RegionReady]: Region {0} - LOGINS DISABLED DURING INITIALIZATION.", m_scene.Name); - if(m_uri != string.Empty) + if (m_uri != string.Empty) { RRAlert("disabled"); } } } - void OnRezScript (uint localID, UUID itemID, string script, int startParam, bool postOnRez, string engine, int stateSource) + void OnRezScript(uint localID, UUID itemID, string script, int startParam, bool postOnRez, string engine, int stateSource) { if (!m_ScriptRez) { @@ -132,11 +131,12 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady if (!m_enabled) return; - m_scene.EventManager.OnEmptyScriptCompileQueue -= OnEmptyScriptCompileQueue; m_scene.EventManager.OnOarFileLoaded -= OnOarFileLoaded; - m_scene.EventManager.OnLoginsEnabled -= OnLoginsEnabled; - if(m_uri != string.Empty) + if (m_disable_logins) + m_scene.EventManager.OnLoginsEnabled -= OnLoginsEnabled; + + if (m_uri != string.Empty) { RRAlert("shutdown"); } @@ -159,7 +159,6 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady #endregion - void OnEmptyScriptCompileQueue(int numScriptsFailed, string message) { m_log.DebugFormat("[RegionReady]: Script compile queue empty!"); @@ -216,27 +215,24 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady // empty compile queue void OnLoginsEnabled(string regionName) { - if (m_disable_logins == true) + if (m_scene.StartDisabled == false) { - if (m_scene.StartDisabled == false) - { - m_scene.LoginsDisabled = false; - m_scene.LoginLock = false; + m_scene.LoginsDisabled = false; + m_scene.LoginLock = false; - m_scene.EventManager.OnEmptyScriptCompileQueue -= OnEmptyScriptCompileQueue; + // m_log.InfoFormat("[RegionReady]: Logins enabled for {0}, Oar {1}", + // m_scene.RegionInfo.RegionName, m_oarFileLoading.ToString()); - // m_log.InfoFormat("[RegionReady]: Logins enabled for {0}, Oar {1}", - // m_scene.RegionInfo.RegionName, m_oarFileLoading.ToString()); + m_log.InfoFormat( + "[RegionReady]: INITIALIZATION COMPLETE FOR {0} - LOGINS ENABLED", m_scene.Name); - m_log.InfoFormat( - "[RegionReady]: INITIALIZATION COMPLETE FOR {0} - LOGINS ENABLED", m_scene.Name); - - if (m_uri != string.Empty) - { - RRAlert("enabled"); - } + if (m_uri != string.Empty) + { + RRAlert("enabled"); } } + + m_scene.EventManager.OnEmptyScriptCompileQueue -= OnEmptyScriptCompileQueue; } public void OarLoadingAlert(string msg) -- cgit v1.1 From 0dd14ca0a3c78ea4b8d02b1024ac8be8404ae427 Mon Sep 17 00:00:00 2001 From: Dan Lake Date: Wed, 18 Jul 2012 13:05:48 -0700 Subject: Missing parameter in log error message was throwing exception --- OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs index 661e03c..305f8a4 100644 --- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs +++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs @@ -100,7 +100,7 @@ namespace OpenSim.Region.Framework.Scenes { m_log.WarnFormat( "[SCENE COMMUNICATION SERVICE]: Region {0} failed to inform neighbour at {1}-{2} that it is up.", - x / Constants.RegionSize, y / Constants.RegionSize); + m_scene.Name, x / Constants.RegionSize, y / Constants.RegionSize); } } -- cgit v1.1 From 6460e587c470361173291337ad222f48c13a10ce Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 18 Jul 2012 21:29:12 +0100 Subject: Pass entire scene object in OnLoginsEnabled event rather than just the region name. This saves listeners from having to re-retrieve the scene from their own lists, which won't work anyway if multiple regions with the same name have been allowed --- .../MapImage/MapImageServiceModule.cs | 13 ++---------- OpenSim/Region/Framework/Scenes/EventManager.cs | 7 +++---- OpenSim/Region/Framework/Scenes/Scene.cs | 2 +- .../RegionReadyModule/RegionReadyModule.cs | 24 ++++++++++++++-------- 4 files changed, 22 insertions(+), 24 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs index 322a9f8..9033460 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs @@ -164,20 +164,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage #endregion ISharedRegionModule - void OnLoginsEnabled(string regionName) + void OnLoginsEnabled(IScene scene) { - Scene scene = null; - foreach (Scene s in m_scenes.Values) - if (s.RegionInfo.RegionName == regionName) - { - scene = s; - break; - } - if (scene != null) - UploadMapTile(scene); + UploadMapTile(scene); } - /// /// /// diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index f92ed8e..e2380b7 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -496,14 +496,13 @@ namespace OpenSim.Region.Framework.Scenes public delegate void RegionHeartbeatEnd(Scene scene); public event RegionHeartbeatEnd OnRegionHeartbeatEnd; - public delegate void LoginsEnabled(string regionName); - /// /// This should only fire in all circumstances if the RegionReady module is active. /// /// /// TODO: Fire this even when the RegionReady module is not active. /// + public delegate void LoginsEnabled(IScene scene); public event LoginsEnabled OnLoginsEnabled; public delegate void PrimsLoaded(Scene s); @@ -2477,7 +2476,7 @@ namespace OpenSim.Region.Framework.Scenes } } - public void TriggerLoginsEnabled (string regionName) + public void TriggerLoginsEnabled(Scene scene) { LoginsEnabled handler = OnLoginsEnabled; @@ -2487,7 +2486,7 @@ namespace OpenSim.Region.Framework.Scenes { try { - d(regionName); + d(scene); } catch (Exception e) { diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index de2b192..8a28ee4 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1493,7 +1493,7 @@ namespace OpenSim.Region.Framework.Scenes { // need to be able to tell these have changed in RegionReady LoginLock = false; - EventManager.TriggerLoginsEnabled(RegionInfo.RegionName); + EventManager.TriggerLoginsEnabled(this); } // For RegionReady lockouts diff --git a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs index aeab61c..29515de 100644 --- a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs @@ -59,7 +59,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady private bool m_disable_logins; private string m_uri = string.Empty; - Scene m_scene = null; + Scene m_scene; #region INonSharedRegionModule interface @@ -192,7 +192,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady m_scene.RegionInfo.RegionName, c.Message, m_channelNotify); m_scene.EventManager.TriggerOnChatBroadcast(this, c); - m_scene.EventManager.TriggerLoginsEnabled(m_scene.RegionInfo.RegionName); + m_scene.EventManager.TriggerLoginsEnabled(m_scene); m_scene.SceneGridService.InformNeighborsThatRegionisUp(m_scene.RequestModuleInterface(), m_scene.RegionInfo); } } @@ -200,20 +200,28 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady void OnOarFileLoaded(Guid requestId, string message) { m_oarFileLoading = true; + if (message==String.Empty) { m_lastOarLoadedOk = true; - } else { + } + else + { m_log.WarnFormat("[RegionReady]: Oar file load errors: {0}", message); m_lastOarLoadedOk = false; } } - // This will be triggerd by Scene if we have no scripts - // m_ScriptsRezzing will be false if there were none - // else it will be true and we should wait on the - // empty compile queue - void OnLoginsEnabled(string regionName) + /// + /// This will be triggered by Scene directly if it contains no scripts on startup. + /// + /// + /// m_ScriptsRezzing will be false if there were none + /// else it will be true and we should wait on the + /// empty compile queue + /// + /// + void OnLoginsEnabled(IScene scene) { if (m_scene.StartDisabled == false) { -- cgit v1.1 From 4973fddc51a4a9e3952bd2decd0ea1842b742141 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 18 Jul 2012 21:52:07 +0100 Subject: Establish EventManager.OnRegionReady event. This will only be triggerred once when the region is ready. Switch MapImageServiceModule to use this. --- .../MapImage/MapImageServiceModule.cs | 10 ++---- OpenSim/Region/Framework/Scenes/EventManager.cs | 37 ++++++++++++++++++++-- OpenSim/Region/Framework/Scenes/Scene.cs | 1 + .../RegionReadyModule/RegionReadyModule.cs | 2 ++ 4 files changed, 39 insertions(+), 11 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs index 9033460..5641804 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs @@ -146,10 +146,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage lock (m_scenes) m_scenes[scene.RegionInfo.RegionID] = scene; - scene.EventManager.OnLoginsEnabled += OnLoginsEnabled; + scene.EventManager.OnRegionReady += s => UploadMapTile(s); } - /// /// /// @@ -163,12 +162,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage } #endregion ISharedRegionModule - - void OnLoginsEnabled(IScene scene) - { - UploadMapTile(scene); - } - + /// /// /// diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index e2380b7..714d70d 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -505,6 +505,16 @@ namespace OpenSim.Region.Framework.Scenes public delegate void LoginsEnabled(IScene scene); public event LoginsEnabled OnLoginsEnabled; + /// + /// Fired when a region is considered ready for use. + /// + /// + /// A region is considered ready when startup operations such as loading of scripts already on the region + /// have been completed. + /// + public delegate void RegionReady(IScene scene); + public event RegionReady OnRegionReady; + public delegate void PrimsLoaded(Scene s); public event PrimsLoaded OnPrimsLoaded; @@ -2476,11 +2486,11 @@ namespace OpenSim.Region.Framework.Scenes } } - public void TriggerLoginsEnabled(Scene scene) + public void TriggerLoginsEnabled(IScene scene) { LoginsEnabled handler = OnLoginsEnabled; - if ( handler != null) + if (handler != null) { foreach (LoginsEnabled d in handler.GetInvocationList()) { @@ -2490,7 +2500,28 @@ namespace OpenSim.Region.Framework.Scenes } catch (Exception e) { - m_log.ErrorFormat("[EVENT MANAGER]: Delegate for LoginsEnabled failed - continuing {0} - {1}", + m_log.ErrorFormat("[EVENT MANAGER]: Delegate for OnLoginsEnabled failed - continuing {0} - {1}", + e.Message, e.StackTrace); + } + } + } + } + + public void TriggerRegionReady(IScene scene) + { + RegionReady handler = OnRegionReady; + + if (handler != null) + { + foreach (RegionReady d in handler.GetInvocationList()) + { + try + { + d(scene); + } + catch (Exception e) + { + m_log.ErrorFormat("[EVENT MANAGER]: Delegate for OnRegionReady 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 8a28ee4..12cc0d3 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1501,6 +1501,7 @@ namespace OpenSim.Region.Framework.Scenes { m_log.InfoFormat("[REGION]: Enabling logins for {0}", RegionInfo.RegionName); LoginsDisabled = false; + EventManager.TriggerRegionReady(this); } m_sceneGridService.InformNeighborsThatRegionisUp(RequestModuleInterface(), RegionInfo); diff --git a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs index 29515de..e09e633 100644 --- a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs @@ -238,6 +238,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady { RRAlert("enabled"); } + + m_scene.EventManager.TriggerRegionReady(m_scene); } m_scene.EventManager.OnEmptyScriptCompileQueue -= OnEmptyScriptCompileQueue; -- cgit v1.1 From 58b72933c814ed393bdf29622d218dd66805af4d Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 18 Jul 2012 22:09:20 +0100 Subject: Fix bug where region ready was being triggered twice in quick succession if a region contained no scripts. --- OpenSim/Region/Framework/Scenes/Scene.cs | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 12cc0d3..cadcec0 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1488,22 +1488,25 @@ namespace OpenSim.Region.Framework.Scenes IConfig startupConfig = m_config.Configs["Startup"]; if (startupConfig == null || !startupConfig.GetBoolean("StartDisabled", false)) { - // This handles a case of a region having no scripts for the RegionReady module - if (m_sceneGraph.GetActiveScriptsCount() == 0) + if (LoginLock) { - // need to be able to tell these have changed in RegionReady - LoginLock = false; - EventManager.TriggerLoginsEnabled(this); + // This handles a case of a region having no scripts for the RegionReady module + if (m_sceneGraph.GetActiveScriptsCount() == 0) + { + // XXX: need to be able to tell these have changed in RegionReady, since it will not + // detect a scenario where the region has no scripts - it's listening to the + // script compile queue. + EventManager.TriggerLoginsEnabled(this); + } } - - // For RegionReady lockouts - if (!LoginLock) + else { m_log.InfoFormat("[REGION]: Enabling logins for {0}", RegionInfo.RegionName); LoginsDisabled = false; + EventManager.TriggerLoginsEnabled(this); EventManager.TriggerRegionReady(this); } - + m_sceneGridService.InformNeighborsThatRegionisUp(RequestModuleInterface(), RegionInfo); } else -- cgit v1.1 From d97e27434c27b02e1b104abb5577d42452b39452 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 18 Jul 2012 22:17:39 +0100 Subject: Fix bug where region ready would be triggered a second time if a script was rezzed on a previously script-free region. There is no need to listen for OnRezScript in RegionReadyModule since OnEmptyScriptCompileQueue will only fire if scripts were compiled. --- .../RegionReadyModule/RegionReadyModule.cs | 53 ++++++++++------------ 1 file changed, 23 insertions(+), 30 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs index e09e633..6b09c3b 100644 --- a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs @@ -99,14 +99,15 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady m_lastOarLoadedOk = true; m_scene.EventManager.OnOarFileLoaded += OnOarFileLoaded; - m_scene.EventManager.OnRezScript += OnRezScript; m_log.DebugFormat("[RegionReady]: Enabled for region {0}", scene.RegionInfo.RegionName); if (m_disable_logins) { + m_scene.LoginLock = true; m_scene.EventManager.OnLoginsEnabled += OnLoginsEnabled; - scene.LoginLock = true; + m_scene.EventManager.OnEmptyScriptCompileQueue += OnEmptyScriptCompileQueue; + m_log.InfoFormat("[RegionReady]: Region {0} - LOGINS DISABLED DURING INITIALIZATION.", m_scene.Name); if (m_uri != string.Empty) @@ -116,16 +117,6 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady } } - void OnRezScript(uint localID, UUID itemID, string script, int startParam, bool postOnRez, string engine, int stateSource) - { - if (!m_ScriptRez) - { - m_ScriptRez = true; - m_scene.EventManager.OnEmptyScriptCompileQueue += OnEmptyScriptCompileQueue; - m_scene.EventManager.OnRezScript -= OnRezScript; - } - } - public void RemoveRegion(Scene scene) { if (!m_enabled) @@ -134,7 +125,10 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady m_scene.EventManager.OnOarFileLoaded -= OnOarFileLoaded; if (m_disable_logins) + { m_scene.EventManager.OnLoginsEnabled -= OnLoginsEnabled; + m_scene.EventManager.OnEmptyScriptCompileQueue -= OnEmptyScriptCompileQueue; + } if (m_uri != string.Empty) { @@ -249,25 +243,24 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady { // Let's bypass this for now until some better feedback can be established // - return; - if (msg == "load") - { - m_scene.EventManager.OnEmptyScriptCompileQueue += OnEmptyScriptCompileQueue; - m_scene.EventManager.OnOarFileLoaded += OnOarFileLoaded; - m_scene.EventManager.OnLoginsEnabled += OnLoginsEnabled; - m_scene.EventManager.OnRezScript += OnRezScript; - m_oarFileLoading = true; - m_firstEmptyCompileQueue = true; - - m_scene.LoginsDisabled = true; - m_scene.LoginLock = true; - if ( m_uri != string.Empty ) - { - RRAlert("loading oar"); - RRAlert("disabled"); - } - } +// if (msg == "load") +// { +// m_scene.EventManager.OnEmptyScriptCompileQueue += OnEmptyScriptCompileQueue; +// m_scene.EventManager.OnOarFileLoaded += OnOarFileLoaded; +// m_scene.EventManager.OnLoginsEnabled += OnLoginsEnabled; +// m_scene.EventManager.OnRezScript += OnRezScript; +// m_oarFileLoading = true; +// m_firstEmptyCompileQueue = true; +// +// m_scene.LoginsDisabled = true; +// m_scene.LoginLock = true; +// if ( m_uri != string.Empty ) +// { +// RRAlert("loading oar"); +// RRAlert("disabled"); +// } +// } } public void RRAlert(string status) -- cgit v1.1 From 1971b6bb4f0f15c08dedee95e730ff6485d8c7cf Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 18 Jul 2012 22:24:52 +0100 Subject: Stop the 15 second initial script compile wait if a script is being rezzed on a previously empty region. --- OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'OpenSim') diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index 7a9c80c..da344d6 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -644,6 +644,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine m_Scene.EventManager.OnGetScriptRunning += OnGetScriptRunning; m_Scene.EventManager.OnShutdown += OnShutdown; + // 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; + if (m_SleepTime > 0) { m_ThreadPool.QueueWorkItem(new WorkItemCallback(this.DoMaintenance), -- cgit v1.1 From 528004d34988d8d2349f18ff7d78c6dd50ab8b2d Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 18 Jul 2012 23:35:05 +0100 Subject: Perform other region ready actions even if simulator is configured to leave logins disabled on startup. --- .../Framework/Interfaces/IRegionReadyModule.cs | 11 +++++- OpenSim/Region/Framework/Scenes/EventManager.cs | 2 +- OpenSim/Region/Framework/Scenes/Scene.cs | 37 +++++++++--------- .../RegionReadyModule/RegionReadyModule.cs | 45 +++++++++------------- 4 files changed, 48 insertions(+), 47 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Framework/Interfaces/IRegionReadyModule.cs b/OpenSim/Region/Framework/Interfaces/IRegionReadyModule.cs index aa4a757..136ca92 100644 --- a/OpenSim/Region/Framework/Interfaces/IRegionReadyModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IRegionReadyModule.cs @@ -25,14 +25,23 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - using System; +using OpenSim.Framework; namespace OpenSim.Region.Framework.Interfaces { public interface IRegionReadyModule { void OarLoadingAlert(string msg); + + /// + /// Trigger region ready status manually. + /// + /// + /// This should be called by the scene if the IRegionReadyModule has set Scene.LoginLock == true + /// + /// + void TriggerRegionReady(IScene scene); } } diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index 714d70d..b8ae0ac 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -2506,7 +2506,7 @@ namespace OpenSim.Region.Framework.Scenes } } } - + public void TriggerRegionReady(IScene scene) { RegionReady handler = OnRegionReady; diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index cadcec0..00aa0ea 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -702,6 +702,8 @@ namespace OpenSim.Region.Framework.Scenes { IConfig startupConfig = m_config.Configs["Startup"]; + StartDisabled = startupConfig.GetBoolean("StartDisabled", false); + m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance", m_defaultDrawDistance); m_useBackup = startupConfig.GetBoolean("UseSceneBackup", m_useBackup); if (!m_useBackup) @@ -1484,35 +1486,32 @@ namespace OpenSim.Region.Framework.Scenes // this is a rare case where we know we have just went through a long cycle of heap // allocations, and there is no more work to be done until someone logs in GC.Collect(); - - IConfig startupConfig = m_config.Configs["Startup"]; - if (startupConfig == null || !startupConfig.GetBoolean("StartDisabled", false)) + + if (!LoginLock) { - if (LoginLock) - { - // This handles a case of a region having no scripts for the RegionReady module - if (m_sceneGraph.GetActiveScriptsCount() == 0) - { - // XXX: need to be able to tell these have changed in RegionReady, since it will not - // detect a scenario where the region has no scripts - it's listening to the - // script compile queue. - EventManager.TriggerLoginsEnabled(this); - } - } - else + if (!StartDisabled) { m_log.InfoFormat("[REGION]: Enabling logins for {0}", RegionInfo.RegionName); LoginsDisabled = false; EventManager.TriggerLoginsEnabled(this); - EventManager.TriggerRegionReady(this); } - m_sceneGridService.InformNeighborsThatRegionisUp(RequestModuleInterface(), RegionInfo); + // Region ready should always be triggered whether logins are immediately enabled or not. + EventManager.TriggerRegionReady(this); } else { - StartDisabled = true; - LoginsDisabled = true; + // This handles a case of a region having no scripts for the RegionReady module + if (m_sceneGraph.GetActiveScriptsCount() == 0) + { + // In this case, we leave it to the IRegionReadyModule to enable logins + + // LoginLock can currently only be set by a region module implementation. + // If somehow this hasn't been done then the quickest way to bugfix is to see the + // NullReferenceException + IRegionReadyModule rrm = RequestModuleInterface(); + rrm.TriggerRegionReady(this); + } } } } diff --git a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs index 6b09c3b..8d5b25f 100644 --- a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs @@ -31,16 +31,14 @@ using System.Reflection; using System.Net; using System.IO; using System.Text; - using log4net; using Nini.Config; using OpenMetaverse; using OpenMetaverse.StructuredData; -using OpenSim.Services.Interfaces; - using OpenSim.Framework; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; namespace OpenSim.Region.OptionalModules.Scripting.RegionReady { @@ -105,7 +103,6 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady if (m_disable_logins) { m_scene.LoginLock = true; - m_scene.EventManager.OnLoginsEnabled += OnLoginsEnabled; m_scene.EventManager.OnEmptyScriptCompileQueue += OnEmptyScriptCompileQueue; m_log.InfoFormat("[RegionReady]: Region {0} - LOGINS DISABLED DURING INITIALIZATION.", m_scene.Name); @@ -125,15 +122,10 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady m_scene.EventManager.OnOarFileLoaded -= OnOarFileLoaded; if (m_disable_logins) - { - m_scene.EventManager.OnLoginsEnabled -= OnLoginsEnabled; m_scene.EventManager.OnEmptyScriptCompileQueue -= OnEmptyScriptCompileQueue; - } if (m_uri != string.Empty) - { RRAlert("shutdown"); - } m_scene = null; } @@ -186,8 +178,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady m_scene.RegionInfo.RegionName, c.Message, m_channelNotify); m_scene.EventManager.TriggerOnChatBroadcast(this, c); - m_scene.EventManager.TriggerLoginsEnabled(m_scene); - m_scene.SceneGridService.InformNeighborsThatRegionisUp(m_scene.RequestModuleInterface(), m_scene.RegionInfo); + + TriggerRegionReady(m_scene); } } @@ -207,20 +199,18 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady } /// - /// This will be triggered by Scene directly if it contains no scripts on startup. + /// This will be triggered by Scene directly if it contains no scripts on startup. Otherwise it is triggered + /// when the script compile queue is empty after initial region startup. /// - /// - /// m_ScriptsRezzing will be false if there were none - /// else it will be true and we should wait on the - /// empty compile queue - /// /// - void OnLoginsEnabled(IScene scene) + public void TriggerRegionReady(IScene scene) { - if (m_scene.StartDisabled == false) + m_scene.EventManager.OnEmptyScriptCompileQueue -= OnEmptyScriptCompileQueue; + m_scene.LoginLock = false; + + if (!m_scene.StartDisabled) { m_scene.LoginsDisabled = false; - m_scene.LoginLock = false; // m_log.InfoFormat("[RegionReady]: Logins enabled for {0}, Oar {1}", // m_scene.RegionInfo.RegionName, m_oarFileLoading.ToString()); @@ -228,15 +218,18 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady m_log.InfoFormat( "[RegionReady]: INITIALIZATION COMPLETE FOR {0} - LOGINS ENABLED", m_scene.Name); - if (m_uri != string.Empty) - { - RRAlert("enabled"); - } + m_scene.EventManager.TriggerLoginsEnabled(m_scene); + } + + m_scene.SceneGridService.InformNeighborsThatRegionisUp( + m_scene.RequestModuleInterface(), m_scene.RegionInfo); - m_scene.EventManager.TriggerRegionReady(m_scene); + if (m_uri != string.Empty) + { + RRAlert("enabled"); } - m_scene.EventManager.OnEmptyScriptCompileQueue -= OnEmptyScriptCompileQueue; + m_scene.EventManager.TriggerRegionReady(m_scene); } public void OarLoadingAlert(string msg) -- cgit v1.1 From 64db0bcbd20ce7487a5f7751ba65d0e2f90b0704 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 18 Jul 2012 23:37:41 +0100 Subject: Add back notification to neighbouring regions when RegionReadyModule is not active accidentally just removed in 528004d --- OpenSim/Region/Framework/Scenes/Scene.cs | 3 +++ 1 file changed, 3 insertions(+) (limited to 'OpenSim') diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 00aa0ea..d4ccd41 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1496,6 +1496,9 @@ namespace OpenSim.Region.Framework.Scenes EventManager.TriggerLoginsEnabled(this); } + m_sceneGridService.InformNeighborsThatRegionisUp( + RequestModuleInterface(), RegionInfo); + // Region ready should always be triggered whether logins are immediately enabled or not. EventManager.TriggerRegionReady(this); } -- cgit v1.1 From 6dda7c65ae1d58cac3e8dc2d9d64f56c870df39e Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 19 Jul 2012 00:09:22 +0100 Subject: Add EventManager.OnRegionLoginsStatusChange fired whenever logins are enabled or disabled at any point, not just during initial startup. This replaces EventManager.OnLoginsEnabled which only fired when logins were first enabled and was affected by a bug where it would never fire if the region started with logins disabled. --- OpenSim/Framework/IScene.cs | 5 +++++ .../Region/CoreModules/World/Access/AccessModule.cs | 10 +++++----- OpenSim/Region/Framework/Scenes/EventManager.cs | 21 +++++++++++---------- OpenSim/Region/Framework/Scenes/Scene.cs | 10 +++++----- OpenSim/Region/Framework/Scenes/SceneBase.cs | 18 ++++++++++++++++++ .../Scenes/Tests/ScenePresenceTeleportTests.cs | 2 +- .../RegionReadyModule/RegionReadyModule.cs | 4 +--- OpenSim/Tests/Common/Helpers/SceneHelpers.cs | 2 +- 8 files changed, 47 insertions(+), 25 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Framework/IScene.cs b/OpenSim/Framework/IScene.cs index a9432c2..2c38e0f 100644 --- a/OpenSim/Framework/IScene.cs +++ b/OpenSim/Framework/IScene.cs @@ -66,6 +66,11 @@ namespace OpenSim.Framework IConfigSource Config { get; } + /// + /// Are logins enabled on this simulator? + /// + bool LoginsEnabled { get; set; } + float TimeDilation { get; } bool AllowScriptCrossings { get; } diff --git a/OpenSim/Region/CoreModules/World/Access/AccessModule.cs b/OpenSim/Region/CoreModules/World/Access/AccessModule.cs index 553a32d..e7b1454 100644 --- a/OpenSim/Region/CoreModules/World/Access/AccessModule.cs +++ b/OpenSim/Region/CoreModules/World/Access/AccessModule.cs @@ -129,18 +129,18 @@ namespace OpenSim.Region.CoreModules.World switch (cmd[1]) { case "enable": - scene.LoginsDisabled = false; + scene.LoginsEnabled = true; MainConsole.Instance.Output(String.Format("Logins are enabled for region {0}", scene.RegionInfo.RegionName)); break; case "disable": - scene.LoginsDisabled = true; + scene.LoginsEnabled = false; MainConsole.Instance.Output(String.Format("Logins are disabled for region {0}", scene.RegionInfo.RegionName)); break; case "status": - if (scene.LoginsDisabled) - MainConsole.Instance.Output(String.Format("Login in {0} are disabled", scene.RegionInfo.RegionName)); - else + if (scene.LoginsEnabled) MainConsole.Instance.Output(String.Format("Login in {0} are enabled", scene.RegionInfo.RegionName)); + else + MainConsole.Instance.Output(String.Format("Login in {0} are disabled", scene.RegionInfo.RegionName)); break; default: MainConsole.Instance.Output("Syntax: login enable|disable|status"); diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index b8ae0ac..620b605 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -497,13 +497,14 @@ namespace OpenSim.Region.Framework.Scenes public event RegionHeartbeatEnd OnRegionHeartbeatEnd; /// - /// This should only fire in all circumstances if the RegionReady module is active. + /// Fired when logins to a region are enabled or disabled. /// /// - /// TODO: Fire this even when the RegionReady module is not active. + /// /// - public delegate void LoginsEnabled(IScene scene); - public event LoginsEnabled OnLoginsEnabled; + /// Fired + public event RegionLoginsStatusChange OnRegionLoginsStatusChange; + public delegate void RegionLoginsStatusChange(IScene scene); /// /// Fired when a region is considered ready for use. @@ -512,8 +513,8 @@ 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 delegate void RegionReady(IScene scene); public event RegionReady OnRegionReady; + public delegate void RegionReady(IScene scene); public delegate void PrimsLoaded(Scene s); public event PrimsLoaded OnPrimsLoaded; @@ -2486,13 +2487,13 @@ namespace OpenSim.Region.Framework.Scenes } } - public void TriggerLoginsEnabled(IScene scene) + public void TriggerRegionLoginsStatusChange(IScene scene) { - LoginsEnabled handler = OnLoginsEnabled; + RegionLoginsStatusChange handler = OnRegionLoginsStatusChange; if (handler != null) { - foreach (LoginsEnabled d in handler.GetInvocationList()) + foreach (RegionLoginsStatusChange d in handler.GetInvocationList()) { try { @@ -2500,13 +2501,13 @@ namespace OpenSim.Region.Framework.Scenes } catch (Exception e) { - m_log.ErrorFormat("[EVENT MANAGER]: Delegate for OnLoginsEnabled failed - continuing {0} - {1}", + m_log.ErrorFormat("[EVENT MANAGER]: Delegate for OnRegionLoginsStatusChange failed - continuing {0} - {1}", e.Message, e.StackTrace); } } } } - + public void TriggerRegionReady(IScene scene) { RegionReady handler = OnRegionReady; diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index d4ccd41..6d8ee7b 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -128,9 +128,10 @@ namespace OpenSim.Region.Framework.Scenes // root agents when ACL denies access to root agent public bool m_strictAccessControl = true; public int MaxUndoCount = 5; + // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet; public bool LoginLock = false; - public bool LoginsDisabled = true; + public bool StartDisabled = false; public bool LoadingPrims; public IXfer XferManager; @@ -1478,7 +1479,7 @@ namespace OpenSim.Region.Framework.Scenes // landMS = Util.EnvironmentTickCountSubtract(ldMS); //} - if (LoginsDisabled && Frame == 20) + if (!LoginsEnabled && Frame == 20) { // m_log.DebugFormat("{0} {1} {2}", LoginsDisabled, m_sceneGraph.GetActiveScriptsCount(), LoginLock); @@ -1492,8 +1493,7 @@ namespace OpenSim.Region.Framework.Scenes if (!StartDisabled) { m_log.InfoFormat("[REGION]: Enabling logins for {0}", RegionInfo.RegionName); - LoginsDisabled = false; - EventManager.TriggerLoginsEnabled(this); + LoginsEnabled = true; } m_sceneGridService.InformNeighborsThatRegionisUp( @@ -3460,7 +3460,7 @@ namespace OpenSim.Region.Framework.Scenes agent.startpos ); - if (LoginsDisabled) + if (!LoginsEnabled) { reason = "Logins Disabled"; return false; diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs index f50fbfc..282fc5e 100644 --- a/OpenSim/Region/Framework/Scenes/SceneBase.cs +++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs @@ -106,6 +106,24 @@ namespace OpenSim.Region.Framework.Scenes protected readonly ClientManager m_clientManager = new ClientManager(); + public bool LoginsEnabled + { + get + { + return m_loginsEnabled; + } + + set + { + if (m_loginsEnabled != value) + { + m_loginsEnabled = value; + EventManager.TriggerRegionLoginsStatusChange(this); + } + } + } + private bool m_loginsEnabled; + public float TimeDilation { get { return 1.0f; } diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs index a407f01..37b5184 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs @@ -301,7 +301,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests sp.AbsolutePosition = preTeleportPosition; // Make sceneB refuse CreateAgent - sceneB.LoginsDisabled = true; + sceneB.LoginsEnabled = false; sceneA.RequestTeleportLocation( sp.ControllingClient, diff --git a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs index 8d5b25f..e49ad2a 100644 --- a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs @@ -210,15 +210,13 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady if (!m_scene.StartDisabled) { - m_scene.LoginsDisabled = false; + m_scene.LoginsEnabled = true; // m_log.InfoFormat("[RegionReady]: Logins enabled for {0}, Oar {1}", // m_scene.RegionInfo.RegionName, m_oarFileLoading.ToString()); m_log.InfoFormat( "[RegionReady]: INITIALIZATION COMPLETE FOR {0} - LOGINS ENABLED", m_scene.Name); - - m_scene.EventManager.TriggerLoginsEnabled(m_scene); } m_scene.SceneGridService.InformNeighborsThatRegionisUp( diff --git a/OpenSim/Tests/Common/Helpers/SceneHelpers.cs b/OpenSim/Tests/Common/Helpers/SceneHelpers.cs index 769de83..7598cc3 100644 --- a/OpenSim/Tests/Common/Helpers/SceneHelpers.cs +++ b/OpenSim/Tests/Common/Helpers/SceneHelpers.cs @@ -190,7 +190,7 @@ namespace OpenSim.Tests.Common = physicsPluginManager.GetPhysicsScene("basicphysics", "ZeroMesher", new IniConfigSource(), "test"); testScene.RegionInfo.EstateSettings = new EstateSettings(); - testScene.LoginsDisabled = false; + testScene.LoginsEnabled = true; testScene.RegisterRegionWithGrid(); SceneManager.Add(testScene); -- cgit v1.1 From c0ab406e2e3ab1e1702285c7cd35e1adc6cc593b Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 19 Jul 2012 21:41:13 +0100 Subject: Add basic TestCreateRootScenePresence() regression test --- .../Scenes/Tests/ScenePresenceAgentTests.cs | 279 +++++++++++---------- 1 file changed, 144 insertions(+), 135 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs index 02c45ef..44c1396 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs @@ -53,48 +53,60 @@ namespace OpenSim.Region.Framework.Scenes.Tests /// Scene presence tests /// [TestFixture] - public class ScenePresenceAgentTests + public class ScenePresenceAgentTests : OpenSimTestCase { - public Scene scene, scene2, scene3; - public UUID agent1, agent2, agent3; - public static Random random; - public ulong region1,region2,region3; - public AgentCircuitData acd1; - public SceneObjectGroup sog1, sog2, sog3; - public TestClient testclient; - - [TestFixtureSetUp] - public void Init() +// public Scene scene, scene2, scene3; +// public UUID agent1, agent2, agent3; +// public static Random random; +// public ulong region1, region2, region3; +// public AgentCircuitData acd1; +// public TestClient testclient; + +// [TestFixtureSetUp] +// public void Init() +// { +//// TestHelpers.InMethod(); +//// +//// SceneHelpers sh = new SceneHelpers(); +//// +//// scene = sh.SetupScene("Neighbour x", UUID.Random(), 1000, 1000); +//// scene2 = sh.SetupScene("Neighbour x+1", UUID.Random(), 1001, 1000); +//// scene3 = sh.SetupScene("Neighbour x-1", UUID.Random(), 999, 1000); +//// +//// ISharedRegionModule interregionComms = new LocalSimulationConnectorModule(); +//// interregionComms.Initialise(new IniConfigSource()); +//// interregionComms.PostInitialise(); +//// SceneHelpers.SetupSceneModules(scene, new IniConfigSource(), interregionComms); +//// SceneHelpers.SetupSceneModules(scene2, new IniConfigSource(), interregionComms); +//// SceneHelpers.SetupSceneModules(scene3, new IniConfigSource(), interregionComms); +// +//// agent1 = UUID.Random(); +//// agent2 = UUID.Random(); +//// agent3 = UUID.Random(); +// +//// region1 = scene.RegionInfo.RegionHandle; +//// region2 = scene2.RegionInfo.RegionHandle; +//// region3 = scene3.RegionInfo.RegionHandle; +// } + + [Test] + public void TestCreateRootScenePresence() { TestHelpers.InMethod(); +// TestHelpers.EnableLogging(); + + UUID spUuid = TestHelpers.ParseTail(0x1); + + TestScene scene = new SceneHelpers().SetupScene(); + SceneHelpers.AddScenePresence(scene, spUuid); + + Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(spUuid), Is.Not.Null); + Assert.That(scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1)); - SceneHelpers sh = new SceneHelpers(); - - scene = sh.SetupScene("Neighbour x", UUID.Random(), 1000, 1000); - scene2 = sh.SetupScene("Neighbour x+1", UUID.Random(), 1001, 1000); - scene3 = sh.SetupScene("Neighbour x-1", UUID.Random(), 999, 1000); - - ISharedRegionModule interregionComms = new LocalSimulationConnectorModule(); - interregionComms.Initialise(new IniConfigSource()); - interregionComms.PostInitialise(); - SceneHelpers.SetupSceneModules(scene, new IniConfigSource(), interregionComms); - SceneHelpers.SetupSceneModules(scene2, new IniConfigSource(), interregionComms); - SceneHelpers.SetupSceneModules(scene3, new IniConfigSource(), interregionComms); - - agent1 = UUID.Random(); - agent2 = UUID.Random(); - agent3 = UUID.Random(); - random = new Random(); - sog1 = SceneHelpers.CreateSceneObject(1, agent1); - scene.AddSceneObject(sog1); - sog2 = SceneHelpers.CreateSceneObject(1, agent1); - scene.AddSceneObject(sog2); - sog3 = SceneHelpers.CreateSceneObject(1, agent1); - scene.AddSceneObject(sog3); - - region1 = scene.RegionInfo.RegionHandle; - region2 = scene2.RegionInfo.RegionHandle; - region3 = scene3.RegionInfo.RegionHandle; + ScenePresence sp = scene.GetScenePresence(spUuid); + Assert.That(sp, Is.Not.Null); + Assert.That(sp.IsChildAgent, Is.False); + Assert.That(sp.UUID, Is.EqualTo(spUuid)); } [Test] @@ -106,9 +118,6 @@ namespace OpenSim.Region.Framework.Scenes.Tests TestScene scene = new SceneHelpers().SetupScene(); ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1)); - Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(sp.UUID), Is.Not.Null); - Assert.That(scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1)); - scene.IncomingCloseAgent(sp.UUID); Assert.That(scene.GetScenePresence(sp.UUID), Is.Null); @@ -266,99 +275,99 @@ namespace OpenSim.Region.Framework.Scenes.Tests // but things are synchronous among them. So there should be // 3 threads in here. //[Test] - public void T021_TestCrossToNewRegion() - { - TestHelpers.InMethod(); - - scene.RegisterRegionWithGrid(); - scene2.RegisterRegionWithGrid(); - - // Adding child agent to region 1001 - string reason; - scene2.NewUserConnection(acd1,0, out reason); - scene2.AddNewClient(testclient, PresenceType.User); - - ScenePresence presence = scene.GetScenePresence(agent1); - presence.MakeRootAgent(new Vector3(0,unchecked(Constants.RegionSize-1),0), true); - - ScenePresence presence2 = scene2.GetScenePresence(agent1); - - // Adding neighbour region caps info to presence2 - - string cap = presence.ControllingClient.RequestClientInfo().CapsPath; - presence2.AddNeighbourRegion(region1, cap); - - Assert.That(presence.IsChildAgent, Is.False, "Did not start root in origin region."); - Assert.That(presence2.IsChildAgent, Is.True, "Is not a child on destination region."); - - // Cross to x+1 - presence.AbsolutePosition = new Vector3(Constants.RegionSize+1,3,100); - presence.Update(); - - EventWaitHandle wh = new EventWaitHandle (false, EventResetMode.AutoReset, "Crossing"); - - // Mimicking communication between client and server, by waiting OK from client - // sent by TestClient.CrossRegion call. Originally, this is network comm. - if (!wh.WaitOne(5000,false)) - { - presence.Update(); - if (!wh.WaitOne(8000,false)) - throw new ArgumentException("1 - Timeout waiting for signal/variable."); - } - - // This is a TestClient specific method that fires OnCompleteMovementToRegion event, which - // would normally be fired after receiving the reply packet from comm. done on the last line. - testclient.CompleteMovement(); - - // Crossings are asynchronous - int timer = 10; - - // Make sure cross hasn't already finished - if (!presence.IsInTransit && !presence.IsChildAgent) - { - // If not and not in transit yet, give it some more time - Thread.Sleep(5000); - } - - // Enough time, should at least be in transit by now. - while (presence.IsInTransit && timer > 0) - { - Thread.Sleep(1000); - timer-=1; - } - - Assert.That(timer,Is.GreaterThan(0),"Timed out waiting to cross 2->1."); - Assert.That(presence.IsChildAgent, Is.True, "Did not complete region cross as expected."); - Assert.That(presence2.IsChildAgent, Is.False, "Did not receive root status after receiving agent."); - - // Cross Back - presence2.AbsolutePosition = new Vector3(-10, 3, 100); - presence2.Update(); - - if (!wh.WaitOne(5000,false)) - { - presence2.Update(); - if (!wh.WaitOne(8000,false)) - throw new ArgumentException("2 - Timeout waiting for signal/variable."); - } - testclient.CompleteMovement(); - - if (!presence2.IsInTransit && !presence2.IsChildAgent) - { - // If not and not in transit yet, give it some more time - Thread.Sleep(5000); - } - - // Enough time, should at least be in transit by now. - while (presence2.IsInTransit && timer > 0) - { - Thread.Sleep(1000); - timer-=1; - } - - Assert.That(timer,Is.GreaterThan(0),"Timed out waiting to cross 1->2."); - Assert.That(presence2.IsChildAgent, Is.True, "Did not return from region as expected."); - Assert.That(presence.IsChildAgent, Is.False, "Presence was not made root in old region again."); - } +// public void T021_TestCrossToNewRegion() +// { +// TestHelpers.InMethod(); +// +// scene.RegisterRegionWithGrid(); +// scene2.RegisterRegionWithGrid(); +// +// // Adding child agent to region 1001 +// string reason; +// scene2.NewUserConnection(acd1,0, out reason); +// scene2.AddNewClient(testclient, PresenceType.User); +// +// ScenePresence presence = scene.GetScenePresence(agent1); +// presence.MakeRootAgent(new Vector3(0,unchecked(Constants.RegionSize-1),0), true); +// +// ScenePresence presence2 = scene2.GetScenePresence(agent1); +// +// // Adding neighbour region caps info to presence2 +// +// string cap = presence.ControllingClient.RequestClientInfo().CapsPath; +// presence2.AddNeighbourRegion(region1, cap); +// +// Assert.That(presence.IsChildAgent, Is.False, "Did not start root in origin region."); +// Assert.That(presence2.IsChildAgent, Is.True, "Is not a child on destination region."); +// +// // Cross to x+1 +// presence.AbsolutePosition = new Vector3(Constants.RegionSize+1,3,100); +// presence.Update(); +// +// EventWaitHandle wh = new EventWaitHandle (false, EventResetMode.AutoReset, "Crossing"); +// +// // Mimicking communication between client and server, by waiting OK from client +// // sent by TestClient.CrossRegion call. Originally, this is network comm. +// if (!wh.WaitOne(5000,false)) +// { +// presence.Update(); +// if (!wh.WaitOne(8000,false)) +// throw new ArgumentException("1 - Timeout waiting for signal/variable."); +// } +// +// // This is a TestClient specific method that fires OnCompleteMovementToRegion event, which +// // would normally be fired after receiving the reply packet from comm. done on the last line. +// testclient.CompleteMovement(); +// +// // Crossings are asynchronous +// int timer = 10; +// +// // Make sure cross hasn't already finished +// if (!presence.IsInTransit && !presence.IsChildAgent) +// { +// // If not and not in transit yet, give it some more time +// Thread.Sleep(5000); +// } +// +// // Enough time, should at least be in transit by now. +// while (presence.IsInTransit && timer > 0) +// { +// Thread.Sleep(1000); +// timer-=1; +// } +// +// Assert.That(timer,Is.GreaterThan(0),"Timed out waiting to cross 2->1."); +// Assert.That(presence.IsChildAgent, Is.True, "Did not complete region cross as expected."); +// Assert.That(presence2.IsChildAgent, Is.False, "Did not receive root status after receiving agent."); +// +// // Cross Back +// presence2.AbsolutePosition = new Vector3(-10, 3, 100); +// presence2.Update(); +// +// if (!wh.WaitOne(5000,false)) +// { +// presence2.Update(); +// if (!wh.WaitOne(8000,false)) +// throw new ArgumentException("2 - Timeout waiting for signal/variable."); +// } +// testclient.CompleteMovement(); +// +// if (!presence2.IsInTransit && !presence2.IsChildAgent) +// { +// // If not and not in transit yet, give it some more time +// Thread.Sleep(5000); +// } +// +// // Enough time, should at least be in transit by now. +// while (presence2.IsInTransit && timer > 0) +// { +// Thread.Sleep(1000); +// timer-=1; +// } +// +// Assert.That(timer,Is.GreaterThan(0),"Timed out waiting to cross 1->2."); +// Assert.That(presence2.IsChildAgent, Is.True, "Did not return from region as expected."); +// Assert.That(presence.IsChildAgent, Is.False, "Presence was not made root in old region again."); +// } } } \ No newline at end of file -- cgit v1.1 From e9a121e1b203e8880bcaf85d35612fc6706b281a Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 19 Jul 2012 21:54:50 +0100 Subject: Add TestCreateDuplicateRootScenePresence() regression test. --- OpenSim/Region/Framework/Scenes/Scene.cs | 17 ++++++++++++++++ OpenSim/Region/Framework/Scenes/SceneGraph.cs | 2 +- .../Scenes/Tests/ScenePresenceAgentTests.cs | 23 ++++++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 6d8ee7b..36452de 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -4470,6 +4470,23 @@ namespace OpenSim.Region.Framework.Scenes } /// + /// Gets all the scene presences in this scene. + /// + /// + /// This method will return both root and child scene presences. + /// + /// Consider using ForEachScenePresence() or ForEachRootScenePresence() if possible since these will not + /// involving creating a new List object. + /// + /// + /// A list of the scene presences. Adding or removing from the list will not affect the presences in the scene. + /// + public List GetScenePresences() + { + return new List(m_sceneGraph.GetScenePresences()); + } + + /// /// Performs action on all avatars in the scene (root scene presences) /// Avatars may be an NPC or a 'real' client. /// diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 2be5364..ba68dfa 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -768,7 +768,7 @@ namespace OpenSim.Region.Framework.Scenes /// pass a delegate to ForEachScenePresence. /// /// - private List GetScenePresences() + protected internal List GetScenePresences() { return m_scenePresenceArray; } diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs index 44c1396..5758869 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs @@ -107,6 +107,29 @@ namespace OpenSim.Region.Framework.Scenes.Tests Assert.That(sp, Is.Not.Null); Assert.That(sp.IsChildAgent, Is.False); Assert.That(sp.UUID, Is.EqualTo(spUuid)); + + Assert.That(scene.GetScenePresences().Count, Is.EqualTo(1)); + } + + [Test] + public void TestCreateDuplicateRootScenePresence() + { + TestHelpers.InMethod(); +// TestHelpers.EnableLogging(); + + UUID spUuid = TestHelpers.ParseTail(0x1); + + TestScene scene = new SceneHelpers().SetupScene(); + SceneHelpers.AddScenePresence(scene, spUuid); + SceneHelpers.AddScenePresence(scene, spUuid); + + Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(spUuid), Is.Not.Null); + Assert.That(scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1)); + + ScenePresence sp = scene.GetScenePresence(spUuid); + Assert.That(sp, Is.Not.Null); + Assert.That(sp.IsChildAgent, Is.False); + Assert.That(sp.UUID, Is.EqualTo(spUuid)); } [Test] -- cgit v1.1 From ba80f137b58cfacf46fadb3ec8b63af6896c5b43 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 19 Jul 2012 22:32:27 +0100 Subject: Prevent race conditions between two threads that call LLClientView.Close() simultaneously (e.g. ack timeout and an attempt to reconnect) --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 58 ++++++++++++++++------ .../Region/ClientStack/Linden/UDP/LLUDPServer.cs | 29 ++++++----- OpenSim/Region/Framework/Scenes/Scene.cs | 6 +-- 3 files changed, 60 insertions(+), 33 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 73cdec3..ae5207b 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -347,8 +347,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP private int m_animationSequenceNumber = 1; private bool m_SendLogoutPacketWhenClosing = true; private AgentUpdateArgs lastarg; - private bool m_IsActive = true; - private bool m_IsLoggingOut = false; protected Dictionary m_packetHandlers = new Dictionary(); protected Dictionary m_genericPacketHandlers = new Dictionary(); //PauPaw:Local Generic Message handlers @@ -412,16 +410,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP public uint CircuitCode { get { return m_circuitCode; } } public int MoneyBalance { get { return m_moneyBalance; } } public int NextAnimationSequenceNumber { get { return m_animationSequenceNumber++; } } - public bool IsActive - { - get { return m_IsActive; } - set { m_IsActive = value; } - } - public bool IsLoggingOut - { - get { return m_IsLoggingOut; } - set { m_IsLoggingOut = value; } - } + + /// + /// As well as it's function in IClientAPI, in LLClientView we are locking on this property in order to + /// prevent race conditions by different threads calling Close(). + /// + public bool IsActive { get; set; } + + /// + /// Used to synchronise threads when client is being closed. + /// + public Object CloseSyncLock { get; private set; } + + public bool IsLoggingOut { get; set; } public bool DisableFacelights { @@ -446,6 +447,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP { // DebugPacketLevel = 1; + CloseSyncLock = new Object(); + RegisterInterface(this); RegisterInterface(this); RegisterInterface(this); @@ -478,17 +481,40 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_prioritizer = new Prioritizer(m_scene); RegisterLocalPacketHandlers(); + + IsActive = true; } #region Client Methods /// - /// Shut down the client view + /// Close down the client view /// public void Close() { - IsActive = false; + // We lock here to prevent race conditions between two threads calling close simultaneously (e.g. + // a simultaneous relog just as a client is being closed out due to no packet ack from the old connection. + lock (CloseSyncLock) + { + if (!IsActive) + return; + + IsActive = false; + CloseWithoutChecks(); + } + } + /// + /// Closes down the client view without first checking whether it is active. + /// + /// + /// This exists because LLUDPServer has to set IsActive = false in earlier synchronous code before calling + /// CloseWithoutIsActiveCheck asynchronously. + /// + /// Callers must lock ClosingSyncLock before calling. + /// + public void CloseWithoutChecks() + { m_log.DebugFormat( "[CLIENT]: Close has been called for {0} attached to scene {1}", Name, m_scene.RegionInfo.RegionName); @@ -3567,7 +3593,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP public void SendCoarseLocationUpdate(List users, List CoarseLocations) { - if (!IsActive) return; // We don't need to update inactive clients. + // We don't need to update inactive clients. + if (!IsActive) + return; CoarseLocationUpdatePacket loc = (CoarseLocationUpdatePacket)PacketPool.Instance.GetPacket(PacketType.CoarseLocationUpdate); loc.Header.Reliable = false; diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index 097f109..746eb90 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs @@ -1123,22 +1123,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// regular client pings. /// /// - private void DeactivateClientDueToTimeout(IClientAPI client) + private void DeactivateClientDueToTimeout(LLClientView client) { - // We must set IsActive synchronously so that we can stop the packet loop reinvoking this method, even - // though it's set later on by LLClientView.Close() - client.IsActive = false; - - m_log.WarnFormat( - "[LLUDPSERVER]: Ack timeout, disconnecting {0} agent for {1} in {2}", - client.SceneAgent.IsChildAgent ? "child" : "root", client.Name, m_scene.RegionInfo.RegionName); - - StatsManager.SimExtraStats.AddAbnormalClientThreadTermination(); - - if (!client.SceneAgent.IsChildAgent) - client.Kick("Simulator logged you out due to connection timeout"); - - client.Close(); + lock (client.CloseSyncLock) + { + m_log.WarnFormat( + "[LLUDPSERVER]: Ack timeout, disconnecting {0} agent for {1} in {2}", + client.SceneAgent.IsChildAgent ? "child" : "root", client.Name, m_scene.RegionInfo.RegionName); + + StatsManager.SimExtraStats.AddAbnormalClientThreadTermination(); + + if (!client.SceneAgent.IsChildAgent) + client.Kick("Simulator logged you out due to connection timeout"); + + client.CloseWithoutChecks(); + } } private void IncomingPacketHandler() diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 36452de..51a6820 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -3517,8 +3517,8 @@ namespace OpenSim.Region.Framework.Scenes // We have a zombie from a crashed session. // Or the same user is trying to be root twice here, won't work. // Kill it. - m_log.DebugFormat( - "[SCENE]: Zombie scene presence detected for {0} {1} in {2}", + m_log.WarnFormat( + "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.", sp.Name, sp.UUID, RegionInfo.RegionName); sp.ControllingClient.Close(); @@ -4474,7 +4474,7 @@ namespace OpenSim.Region.Framework.Scenes /// /// /// This method will return both root and child scene presences. - /// + /// /// Consider using ForEachScenePresence() or ForEachRootScenePresence() if possible since these will not /// involving creating a new List object. /// -- cgit v1.1 From ccc7e75ce4773d0dd5fa2f28a76da57cde76c126 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 19 Jul 2012 22:37:48 +0100 Subject: minor: remove some mono compiler warnings --- OpenSim/Region/OptionalModules/PhysicsParameters/PhysicsParameters.cs | 2 +- .../OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/OptionalModules/PhysicsParameters/PhysicsParameters.cs b/OpenSim/Region/OptionalModules/PhysicsParameters/PhysicsParameters.cs index e452124..40f7fbc 100755 --- a/OpenSim/Region/OptionalModules/PhysicsParameters/PhysicsParameters.cs +++ b/OpenSim/Region/OptionalModules/PhysicsParameters/PhysicsParameters.cs @@ -47,7 +47,7 @@ namespace OpenSim.Region.OptionalModules.PhysicsParameters [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "PhysicsParameters")] public class PhysicsParameters : ISharedRegionModule { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); +// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); // private static string LogHeader = "[PHYSICS PARAMETERS]"; private List m_scenes = new List(); diff --git a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs index e49ad2a..f459b8c 100644 --- a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs @@ -48,7 +48,6 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private IConfig m_config = null; - private bool m_ScriptRez; private bool m_firstEmptyCompileQueue; private bool m_oarFileLoading; private bool m_lastOarLoadedOk; @@ -91,7 +90,6 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady m_scene.RegisterModuleInterface(this); - m_ScriptRez = false; m_firstEmptyCompileQueue = true; m_oarFileLoading = false; m_lastOarLoadedOk = true; -- cgit v1.1 From e94831ddab282f2d84d0dad0b28e7cce6ac4c4b0 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 19 Jul 2012 22:59:28 +0100 Subject: Stop explicitly closing and nulling out Animator in order to prevent NREs in various places due to race conditions. Even where checks are being made they aren't enough since they all assume that the Animator they just checked is still there in the next line, which is not necessarily the case without locking. The memory used is small and these should be GC'd anyway when the SP is released. If this is not happening then the wider problem of old SPs being retained needs to be resolved. --- .../Scenes/Animation/ScenePresenceAnimator.cs | 8 +------- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 22 ++++++---------------- 2 files changed, 7 insertions(+), 23 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs index 14ae287..ff53f45 100644 --- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs +++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs @@ -535,11 +535,5 @@ namespace OpenSim.Region.Framework.Scenes.Animation SendAnimPack(animIDs, sequenceNums, objectIDs); } - - public void Close() - { - m_animations = null; - m_scenePresence = null; - } } -} +} \ No newline at end of file diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 0e7f2e5..548dfd3 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -109,15 +109,10 @@ namespace OpenSim.Region.Framework.Scenes public UUID currentParcelUUID = UUID.Zero; - protected ScenePresenceAnimator m_animator; /// /// The animator for this avatar /// - public ScenePresenceAnimator Animator - { - get { return m_animator; } - private set { m_animator = value; } - } + public ScenePresenceAnimator Animator { get; private set; } /// /// Attachments recorded on this avatar. @@ -2569,8 +2564,7 @@ namespace OpenSim.Region.Framework.Scenes //m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToAgent from {0} ({1}) to {2} ({3})", Name, UUID, avatar.Name, avatar.UUID); avatar.ControllingClient.SendAvatarDataImmediate(this); - if (Animator != null) - Animator.SendAnimPackToClient(avatar.ControllingClient); + Animator.SendAnimPackToClient(avatar.ControllingClient); } /// @@ -3239,14 +3233,12 @@ namespace OpenSim.Region.Framework.Scenes //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f)) // The Physics Scene will send updates every 500 ms grep: PhysicsActor.SubscribeEvents( // as of this comment the interval is set in AddToPhysicalScene - if (Animator != null) - { + // if (m_updateCount > 0) // { - Animator.UpdateMovementAnimations(); + Animator.UpdateMovementAnimations(); // m_updateCount--; // } - } CollisionEventUpdate collisionData = (CollisionEventUpdate)e; Dictionary coldata = collisionData.m_objCollisionList; @@ -3261,7 +3253,7 @@ namespace OpenSim.Region.Framework.Scenes // m_lastColCount = coldata.Count; // } - if (coldata.Count != 0 && Animator != null) + if (coldata.Count != 0) { switch (Animator.CurrentMovementAnimation) { @@ -3371,7 +3363,7 @@ namespace OpenSim.Region.Framework.Scenes ControllingClient.SendHealth(Health); } - public void Close() + protected internal void Close() { // Clear known regions KnownRegions = new Dictionary(); @@ -3387,8 +3379,6 @@ namespace OpenSim.Region.Framework.Scenes // m_reprioritizationTimer.Dispose(); RemoveFromPhysicalScene(); - Animator.Close(); - Animator = null; } public void AddAttachment(SceneObjectGroup gobj) -- cgit v1.1 From c4533e755bd321195056cfbbebc80dcc05998680 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 19 Jul 2012 23:13:08 +0100 Subject: Comment out OnIncomingInstantMessage and OnInstantMessage handlers in GroupsModule, since these led to a private blank method --- .../Region/CoreModules/Avatar/Groups/GroupsModule.cs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/Avatar/Groups/GroupsModule.cs b/OpenSim/Region/CoreModules/Avatar/Groups/GroupsModule.cs index 31363e5..b258e13 100644 --- a/OpenSim/Region/CoreModules/Avatar/Groups/GroupsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Groups/GroupsModule.cs @@ -96,7 +96,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Groups scene.EventManager.OnNewClient += OnNewClient; scene.EventManager.OnClientClosed += OnClientClosed; - scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; +// scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; } public void PostInitialise() @@ -133,7 +133,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Groups private void OnNewClient(IClientAPI client) { // Subscribe to instant messages - client.OnInstantMessage += OnInstantMessage; +// client.OnInstantMessage += OnInstantMessage; client.OnAgentDataUpdateRequest += OnAgentDataUpdateRequest; client.OnUUIDGroupNameRequest += HandleUUIDGroupNameRequest; lock (m_ClientMap) @@ -171,15 +171,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Groups ActiveGroupTitle); } - private void OnInstantMessage(IClientAPI client, GridInstantMessage im) - { - } +// private void OnInstantMessage(IClientAPI client, GridInstantMessage im) +// { +// } - private void OnGridInstantMessage(GridInstantMessage msg) - { - // Trigger the above event handler - OnInstantMessage(null, msg); - } +// private void OnGridInstantMessage(GridInstantMessage msg) +// { +// // Trigger the above event handler +// OnInstantMessage(null, msg); +// } private void HandleUUIDGroupNameRequest(UUID id,IClientAPI remote_client) { -- cgit v1.1 From d1d331a4c02243c8bb4ada60566fa48417c95a5a Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 19 Jul 2012 23:20:03 +0100 Subject: Make LLClientView instant message handling asynchronous rather than synchronous to prevent long operations from holding up all inbound packet processing. Giving a large folder from one avatar to another was causing a long delay when handled synchronously, since it took some time to retrieve the necessary data from the inventory service. Handling this asynchronously instead stops this delay from disrupting all avatars in the scene. This has been shown in OSGrid. I see no reason for not handling all IM messages asynchronously, just as incoming chat is handled asynchronously, so this has been switched for all instant messages. Thanks to Nebadon for testing this change out. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index ae5207b..f7864b8 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -5192,7 +5192,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP AddLocalPacketHandler(PacketType.ChatFromViewer, HandleChatFromViewer); AddLocalPacketHandler(PacketType.AvatarPropertiesUpdate, HandlerAvatarPropertiesUpdate); AddLocalPacketHandler(PacketType.ScriptDialogReply, HandlerScriptDialogReply); - AddLocalPacketHandler(PacketType.ImprovedInstantMessage, HandlerImprovedInstantMessage, false); + AddLocalPacketHandler(PacketType.ImprovedInstantMessage, HandlerImprovedInstantMessage); AddLocalPacketHandler(PacketType.AcceptFriendship, HandlerAcceptFriendship); AddLocalPacketHandler(PacketType.DeclineFriendship, HandlerDeclineFriendship); AddLocalPacketHandler(PacketType.TerminateFriendship, HandlerTerminateFriendship); -- cgit v1.1 From be39f03caa701d2b623e4f2c1c89256df0e85914 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 19 Jul 2012 23:35:56 +0100 Subject: minor: switch around mixed up circuit code and endpoint data in "show connections" region console command --- OpenSim/Region/Application/OpenSim.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs index 230af8e..a4d85ac 100644 --- a/OpenSim/Region/Application/OpenSim.cs +++ b/OpenSim/Region/Application/OpenSim.cs @@ -1145,8 +1145,8 @@ namespace OpenSim c => cdt.AddRow( s.Name, c.Name, - c.RemoteEndPoint.ToString(), c.CircuitCode.ToString(), + c.RemoteEndPoint.ToString(), c.IsActive.ToString()))); MainConsole.Instance.Output(cdt.ToString()); -- cgit v1.1 From fe99948c582cb7a9c0a999bbbc179f254b2e47c7 Mon Sep 17 00:00:00 2001 From: Melanie Date: Fri, 20 Jul 2012 11:54:59 +0200 Subject: Fix the order of operations on detach. The object must always be serialized while still in the scene to avoid losing important script state. DeleteSceneObject can not be called before doing this! --- .../CoreModules/Avatar/Attachments/AttachmentsModule.cs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index d34a8f6..0f3b1e8 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -690,18 +690,22 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments m_scene.EventManager.TriggerOnAttach(so.LocalId, so.FromItemID, UUID.Zero); sp.RemoveAttachment(so); - // We can only remove the script instances from the script engine after we've retrieved their xml state - // when we update the attachment item. - m_scene.DeleteSceneObject(so, false, false); - // Prepare sog for storage so.AttachedAvatar = UUID.Zero; so.RootPart.SetParentLocalId(0); so.IsAttachment = false; - so.AbsolutePosition = so.RootPart.AttachedPos; + + // We cannot use AbsolutePosition here because that would + // attempt to cross the prim as it is detached + so.ForEachPart(x => { x.GroupPosition = so.RootPart.AttachedPos; }); UpdateKnownItem(sp, so, true); - so.RemoveScriptInstances(true); + + // This MUST happen AFTER serialization because it will + // either stop or remove the scripts. Both will cause scripts + // to be serialized in a stopped state with the true run + // state already lost. + m_scene.DeleteSceneObject(so, false, true); } private SceneObjectGroup RezSingleAttachmentFromInventoryInternal( -- cgit v1.1 From 644fb6b013b8c8598c42d19cee67201911f31c2e Mon Sep 17 00:00:00 2001 From: Mic Bowman Date: Fri, 20 Jul 2012 10:25:50 -0700 Subject: Implements a very useful OSSL function to test a string to see if it is a UUID. The function is osIsUUID(). Thanks SignpostMarv! --- .../ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs | 14 ++++++++++++++ .../Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs | 7 +++++++ .../Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs | 5 +++++ 3 files changed, 26 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 4137397..e0b4db6 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -3274,5 +3274,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api InitLSL(); ((LSL_Api)m_LSL_Api).DetachFromAvatar(); } + + /// + /// Checks if thing is a UUID. + /// + /// + /// 1 if thing is a valid UUID, 0 otherwise + public LSL_Integer osIsUUID(string thing) + { + CheckThreatLevel(ThreatLevel.None, "osIsUUID"); + m_host.AddScriptLPS(1); + + UUID test; + return UUID.TryParse(thing, out test) ? 1 : 0; + } } } \ 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 b5416c8..c9403eb 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs @@ -276,5 +276,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces void osSetTerrainTexture(int level, LSL_Key texture); void osSetTerrainTextureHeight(int corner, double low, double high); + + /// + /// Checks if thing is a UUID. + /// + /// + /// 1 if thing is a valid UUID, 0 otherwise + LSL_Integer osIsUUID(string thing); } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs index b40bdf0..99995a7 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs @@ -930,5 +930,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase { m_OSSL_Functions.osSetTerrainTextureHeight(corner, low, high); } + + public LSL_Integer osIsUUID(string thing) + { + return m_OSSL_Functions.osIsUUID(thing); + } } } -- cgit v1.1 From a4281ca014c80ca516e514e9fde9bb3a13e10c97 Mon Sep 17 00:00:00 2001 From: Mic Bowman Date: Fri, 20 Jul 2012 10:48:51 -0700 Subject: Enables support for UUIDs to be returned in lists from modInvoke commands. Thanks SignpostMarv!!! --- .../ScriptEngine/Shared/Api/Implementation/MOD_Api.cs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs index 4bd3dff..7844c75 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs @@ -200,24 +200,34 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api for (int i = 0; i < result.Length; i++) { if (result[i] is string) + { llist[i] = new LSL_String((string)result[i]); + } else if (result[i] is int) + { llist[i] = new LSL_Integer((int)result[i]); + } else if (result[i] is float) + { llist[i] = new LSL_Float((float)result[i]); + } + else if (result[i] is UUID) + { + llist[i] = new LSL_Key(result[i].ToString()); + } else if (result[i] is OpenMetaverse.Vector3) { OpenMetaverse.Vector3 vresult = (OpenMetaverse.Vector3)result[i]; - llist[i] = new LSL_Vector(vresult.X,vresult.Y,vresult.Z); + llist[i] = new LSL_Vector(vresult.X, vresult.Y, vresult.Z); } else if (result[i] is OpenMetaverse.Quaternion) { OpenMetaverse.Quaternion qresult = (OpenMetaverse.Quaternion)result[i]; - llist[i] = new LSL_Rotation(qresult.X,qresult.Y,qresult.Z,qresult.W); + llist[i] = new LSL_Rotation(qresult.X, qresult.Y, qresult.Z, qresult.W); } else { - MODError(String.Format("unknown list element returned by {0}",fname)); + MODError(String.Format("unknown list element {1} returned by {0}", fname, result[i].GetType().Name)); } } -- cgit v1.1 From bcfc392edfb09adbd1cfb21843f2505d9a2adb57 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 20 Jul 2012 21:08:04 +0100 Subject: As per opensim-dev mailing list conversation, introduce OS_NPC constant for use with llSensor() This same constant will later be used with llGetDetectedType(). This constant has a different name from NPC to avoid possible conflict with future LSL changes. This constant has a different value to try and avoid unnecessary conflict with future constants that may use the same value. Using the 'NPC' constant with llSensor() will remain valid but is deprecated. --- .../ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs | 5 +++-- OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs index 3844753..f2c8b60 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs @@ -68,6 +68,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins private const int AGENT = 1; private const int AGENT_BY_USERNAME = 0x10; private const int NPC = 0x20; + private const int OS_NPC = 0x01000000; private const int ACTIVE = 2; private const int PASSIVE = 4; private const int SCRIPTED = 8; @@ -220,7 +221,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins List sensedEntities = new List(); // Is the sensor type is AGENT and not SCRIPTED then include agents - if ((ts.type & (AGENT | AGENT_BY_USERNAME | NPC)) != 0 && (ts.type & SCRIPTED) == 0) + if ((ts.type & (AGENT | AGENT_BY_USERNAME | NPC | OS_NPC)) != 0 && (ts.type & SCRIPTED) == 0) { sensedEntities.AddRange(doAgentSensor(ts)); } @@ -479,7 +480,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins // "[SENSOR REPEAT]: Inspecting scene presence {0}, type {1} on sensor sweep for {2}, type {3}", // presence.Name, presence.PresenceType, ts.name, ts.type); - if ((ts.type & NPC) == 0 && presence.PresenceType == PresenceType.Npc) + if ((ts.type & NPC) == 0 && (ts.type & OS_NPC) == 0 && presence.PresenceType == PresenceType.Npc) { INPC npcData = npcModule.GetNPC(presence.UUID, presence.Scene); if (npcData == null || !npcData.SenseAsAgent) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs index b6c21e6..c3eada0 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs @@ -56,6 +56,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase public const int ACTIVE = 2; public const int PASSIVE = 4; public const int SCRIPTED = 8; + public const int OS_NPC = 0x01000000; public const int CONTROL_FWD = 1; public const int CONTROL_BACK = 2; -- cgit v1.1 From ecf7bb268caaca809905accb4989b0baa467d3ce Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 20 Jul 2012 21:36:33 +0100 Subject: As per opensim-dev mailing list discussion, extend llGetDetectedType() to return OS_NPC if an OS npc is detected. The detection will also return agent is the NPC has been created with the OS_NPC_SENSE_AS_AGENT option. --- OpenSim/Region/ScriptEngine/Shared/Helpers.cs | 33 +++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 5 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs index 8cebb4a..0108f44 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs @@ -35,6 +35,7 @@ using OpenMetaverse; using OpenSim.Framework; using OpenSim.Region.CoreModules; using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.Framework.Interfaces; namespace OpenSim.Region.ScriptEngine.Shared { @@ -82,6 +83,12 @@ namespace OpenSim.Region.ScriptEngine.Shared public class DetectParams { + public const int AGENT = 1; + public const int ACTIVE = 2; + public const int PASSIVE = 4; + public const int SCRIPTED = 8; + public const int OS_NPC = 0x01000000; + public DetectParams() { Key = UUID.Zero; @@ -188,9 +195,25 @@ namespace OpenSim.Region.ScriptEngine.Shared presence.Velocity.Y, presence.Velocity.Z); - Type = 0x01; // Avatar + if (presence.PresenceType != PresenceType.Npc) + { + Type = AGENT; + } + else + { + Type = OS_NPC; + + INPCModule npcModule = scene.RequestModuleInterface(); + INPC npcData = npcModule.GetNPC(presence.UUID, presence.Scene); + + if (npcData.SenseAsAgent) + { + Type |= AGENT; + } + } + if (presence.Velocity != Vector3.Zero) - Type |= 0x02; // Active + Type |= ACTIVE; Group = presence.ControllingClient.ActiveGroupId; @@ -205,15 +228,15 @@ namespace OpenSim.Region.ScriptEngine.Shared Name = part.Name; Owner = part.OwnerID; if (part.Velocity == Vector3.Zero) - Type = 0x04; // Passive + Type = PASSIVE; else - Type = 0x02; // Passive + Type = ACTIVE; foreach (SceneObjectPart p in part.ParentGroup.Parts) { if (p.Inventory.ContainsScripts()) { - Type |= 0x08; // Scripted + Type |= SCRIPTED; // Scripted break; } } -- cgit v1.1 From f9913b6ef7e7f18075e1e42ed5e347ce2a8b8ef5 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Thu, 12 Jul 2012 11:29:45 -0700 Subject: BulletSim: Add detailed and voluminous debug logging that is enabled with an ini configuration parameter. Correct computation of relative offsets of children in a linkset. Remove a prim from any link relationship before deleting it. Minor code flow cleanups. --- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 52 ++++++++++++++---------- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 53 ++++++++++++++++--------- 2 files changed, 65 insertions(+), 40 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 130f1ca..9b28a06 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -42,6 +42,8 @@ public sealed class BSPrim : PhysicsActor private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly string LogHeader = "[BULLETS PRIM]"; + private void DebugLog(string mm, params Object[] xx) { if (_scene.shouldDebugLog) m_log.DebugFormat(mm, xx); } + private IMesh _mesh; private PrimitiveBaseShape _pbs; private ShapeData.PhysicsShapeType _shapeType; @@ -86,8 +88,8 @@ public sealed class BSPrim : PhysicsActor private bool _kinematic; private float _buoyancy; - private List _childrenPrims; private BSPrim _parentPrim; + private List _childrenPrims; private int _subscribedEventsMs = 0; private int _nextCollisionOkTime = 0; @@ -148,6 +150,15 @@ public sealed class BSPrim : PhysicsActor // Undo any vehicle properties _vehicle.ProcessTypeChange(Vehicle.TYPE_NONE); _scene.RemoveVehiclePrim(this); // just to make sure + + // 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; + } + _scene.TaintedObject(delegate() { // everything in the C# world will get garbage collected. Tell the C++ world to free stuff. @@ -202,7 +213,7 @@ public sealed class BSPrim : PhysicsActor // link me to the specified parent public override void link(PhysicsActor obj) { BSPrim parent = obj as BSPrim; - // m_log.DebugFormat("{0}: link {1}/{2} to {3}", LogHeader, _avName, _localID, obj.LocalID); + DebugLog("{0}: link {1}/{2} to {3}", LogHeader, _avName, _localID, obj.LocalID); // TODO: decide if this parent checking needs to happen at taint time if (_parentPrim == null) { @@ -225,7 +236,7 @@ public sealed class BSPrim : PhysicsActor else { // asking to reparent a prim should not happen - m_log.ErrorFormat("{0}: Reparenting a prim. ", LogHeader); + m_log.ErrorFormat("{0}: link(): Reparenting a prim. ", LogHeader); } } } @@ -236,7 +247,8 @@ public sealed class BSPrim : PhysicsActor public override void delink() { // 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 - // m_log.DebugFormat("{0}: delink {1}/{2}", LogHeader, _avName, _localID); + DebugLog("{0}: delink {1}/{2}. Parent={3}", LogHeader, _avName, _localID, + (_parentPrim==null ? "NULL" : _parentPrim._avName+"/"+_parentPrim.LocalID.ToString())); if (_parentPrim != null) { _parentPrim.RemoveChildFromLinkset(this); @@ -252,8 +264,9 @@ public sealed class BSPrim : PhysicsActor { if (!_childrenPrims.Contains(child)) { + DebugLog("{0}: AddChildToLinkset: adding child {1} to {2}", LogHeader, child.LocalID, this.LocalID); _childrenPrims.Add(child); - child.ParentPrim = this; // the child has gained a parent + child._parentPrim = this; // the child has gained a parent RecreateGeomAndObject(); // rebuild my shape with the new child added } }); @@ -269,9 +282,13 @@ public sealed class BSPrim : PhysicsActor { if (_childrenPrims.Contains(child)) { - BulletSimAPI.RemoveConstraint(_scene.WorldID, child.LocalID, this.LocalID); + DebugLog("{0}: RemoveChildFromLinkset: Removing constraint to {1}", LogHeader, child.LocalID); + if (!BulletSimAPI.RemoveConstraintByID(_scene.WorldID, child.LocalID)) + { + m_log.ErrorFormat("{0}: RemoveChildFromLinkset: Failed remove constraint for {1}", LogHeader, child.LocalID); + } _childrenPrims.Remove(child); - child.ParentPrim = null; // the child has lost its parent + child._parentPrim = null; // the child has lost its parent RecreateGeomAndObject(); // rebuild my shape with the child removed } else @@ -282,11 +299,6 @@ public sealed class BSPrim : PhysicsActor return; } - public BSPrim ParentPrim - { - set { _parentPrim = value; } - } - // return true if we are the root of a linkset (there are children to manage) public bool IsRootOfLinkset { @@ -981,7 +993,6 @@ public sealed class BSPrim : PhysicsActor int vi = 0; foreach (OMV.Vector3 vv in vertices) { - // m_log.DebugFormat("{0}: {1}: <{2:0.00}, {3:0.00}, {4:0.00}>", LogHeader, vi / 3, vv.X, vv.Y, vv.Z); verticesAsFloats[vi++] = vv.X; verticesAsFloats[vi++] = vv.Y; verticesAsFloats[vi++] = vv.Z; @@ -1129,7 +1140,6 @@ public sealed class BSPrim : PhysicsActor if (IsRootOfLinkset) { // Create a linkset around this object - // CreateLinksetWithCompoundHull(); CreateLinksetWithConstraints(); } else @@ -1191,33 +1201,33 @@ public sealed class BSPrim : PhysicsActor // TODO: make this more effeicient: a large linkset gets rebuilt over and over and prims are added void CreateLinksetWithConstraints() { - // m_log.DebugFormat("{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 foreach (BSPrim prim in _childrenPrims) { - // m_log.DebugFormat("{0}: CreateLinkset: RemoveConstraint between root prim {1} and child prim {2}", LogHeader, LocalID, prim.LocalID); + DebugLog("{0}: CreateLinkset: RemoveConstraint between root prim {1} and child prim {2}", LogHeader, LocalID, prim.LocalID); BulletSimAPI.RemoveConstraint(_scene.WorldID, LocalID, prim.LocalID); } // create constraints between the root prim and each of the children foreach (BSPrim prim in _childrenPrims) { - // m_log.DebugFormat("{0}: CreateLinkset: AddConstraint between root prim {1} and child prim {2}", LogHeader, LocalID, prim.LocalID); - // Zero motion for children so they don't interpolate prim.ZeroMotion(); // relative position normalized to the root prim - OMV.Vector3 childRelativePosition = (prim._position - this._position) * OMV.Quaternion.Inverse(this._orientation); + OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(this._orientation); + OMV.Vector3 childRelativePosition = (prim._position - this._position) * invThisOrientation; // relative rotation of the child to the parent - OMV.Quaternion relativeRotation = OMV.Quaternion.Inverse(prim._orientation) * this._orientation; + OMV.Quaternion childRelativeRotation = invThisOrientation * prim._orientation; // this is 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, prim.LocalID); BulletSimAPI.AddConstraint(_scene.WorldID, LocalID, prim.LocalID, childRelativePosition, - relativeRotation, + childRelativeRotation, OMV.Vector3.Zero, OMV.Quaternion.Identity, OMV.Vector3.Zero, OMV.Vector3.Zero, diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 417cb5f..eb1d798 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -72,6 +72,8 @@ 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 string BulletSimVersion = "?"; private Dictionary m_avatars = new Dictionary(); @@ -147,6 +149,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters ConfigurationParameters[] m_params; GCHandle m_paramsHandle; + public bool shouldDebugLog { get; private set; } + private BulletSimAPI.DebugLogCallback m_DebugLogCallbackHandle; public BSScene(string identifier) @@ -209,6 +213,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters m_meshLOD = 8f; m_sculptLOD = 32f; + shouldDebugLog = false; m_detailedStatsStep = 0; // disabled m_maxSubSteps = 10; @@ -261,7 +266,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters _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); @@ -347,34 +354,42 @@ public class BSScene : PhysicsScene, IPhysicsParameters public override void RemoveAvatar(PhysicsActor actor) { // m_log.DebugFormat("{0}: RemoveAvatar", LogHeader); - if (actor is BSCharacter) - { - ((BSCharacter)actor).Destroy(); - } - try + BSCharacter bsactor = actor as BSCharacter; + if (bsactor != null) { - lock (m_avatars) m_avatars.Remove(actor.LocalID); - } - catch (Exception e) - { - m_log.WarnFormat("{0}: Attempt to remove avatar that is not in physics scene: {1}", LogHeader, e); + try + { + lock (m_avatars) m_avatars.Remove(actor.LocalID); + } + catch (Exception e) + { + m_log.WarnFormat("{0}: Attempt to remove avatar that is not in physics scene: {1}", LogHeader, e); + } + bsactor.Destroy(); + // bsactor.dispose(); } } public override void RemovePrim(PhysicsActor prim) { - // m_log.DebugFormat("{0}: RemovePrim", LogHeader); - if (prim is BSPrim) - { - ((BSPrim)prim).Destroy(); - } - try + BSPrim bsprim = prim as BSPrim; + if (bsprim != null) { - lock (m_prims) m_prims.Remove(prim.LocalID); + m_log.DebugFormat("{0}: RemovePrim. id={1}/{2}", LogHeader, bsprim.Name, bsprim.LocalID); + try + { + lock (m_prims) m_prims.Remove(bsprim.LocalID); + } + catch (Exception e) + { + m_log.ErrorFormat("{0}: Attempt to remove prim that is not in physics scene: {1}", LogHeader, e); + } + bsprim.Destroy(); + // bsprim.dispose(); } - catch (Exception e) + else { - m_log.WarnFormat("{0}: Attempt to remove prim that is not in physics scene: {1}", LogHeader, e); + m_log.ErrorFormat("{0}: Attempt to remove prim that is not a BSPrim type.", LogHeader); } } -- cgit v1.1 From c400918c84fc89ff0209ee05def3bb46206ba5ee Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Thu, 12 Jul 2012 15:34:25 -0700 Subject: BulletSim: Add PID variables to physical scene. Not PIDing yet, but soon. Cleaned up code and got rid of compile warnings. --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 69 ++++++------ OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 116 +++++++++------------ OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 13 +++ 3 files changed, 97 insertions(+), 101 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index dc0c008..09e1f0c 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -41,7 +41,7 @@ public class BSCharacter : PhysicsActor private BSScene _scene; private String _avName; - private bool _stopped; + // private bool _stopped; private Vector3 _size; private Vector3 _scale; private PrimitiveBaseShape _pbs; @@ -134,9 +134,9 @@ public class BSCharacter : PhysicsActor { base.RequestPhysicsterseUpdate(); } - + // No one calls this method so I don't know what it could possibly mean public override bool Stopped { - get { return _stopped; } + get { return false; } } public override Vector3 Size { get { return _size; } @@ -391,52 +391,47 @@ public class BSCharacter : PhysicsActor _mass = _density * _avatarVolume; } - // Set to 'true' if the individual changed items should be checked - // (someday RequestPhysicsTerseUpdate() will take a bitmap of changed properties) - const bool SHOULD_CHECK_FOR_INDIVIDUAL_CHANGES = false; - // The physics engine says that properties have updated. Update same and inform // the world that things have changed. public void UpdateProperties(EntityProperties entprop) { + /* bool changed = false; - if (SHOULD_CHECK_FOR_INDIVIDUAL_CHANGES) { - // we assign to the local variables so the normal set action does not happen - if (_position != entprop.Position) { - _position = entprop.Position; - changed = true; - } - if (_orientation != entprop.Rotation) { - _orientation = entprop.Rotation; - changed = true; - } - if (_velocity != entprop.Velocity) { - _velocity = entprop.Velocity; - changed = true; - } - if (_acceleration != entprop.Acceleration) { - _acceleration = entprop.Acceleration; - changed = true; - } - if (_rotationalVelocity != entprop.RotationalVelocity) { - _rotationalVelocity = entprop.RotationalVelocity; - changed = true; - } - if (changed) { - // m_log.DebugFormat("{0}: UpdateProperties: id={1}, c={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation); - // Avatar movement is not done by generating this event. There is code in the heartbeat - // loop that updates avatars. - // base.RequestPhysicsterseUpdate(); - } - } - else { + // we assign to the local variables so the normal set action does not happen + if (_position != entprop.Position) { _position = entprop.Position; + changed = true; + } + if (_orientation != entprop.Rotation) { _orientation = entprop.Rotation; + changed = true; + } + if (_velocity != entprop.Velocity) { _velocity = entprop.Velocity; + changed = true; + } + if (_acceleration != entprop.Acceleration) { _acceleration = entprop.Acceleration; + changed = true; + } + if (_rotationalVelocity != entprop.RotationalVelocity) { _rotationalVelocity = entprop.RotationalVelocity; + changed = true; + } + if (changed) { + // m_log.DebugFormat("{0}: UpdateProperties: id={1}, c={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation); + // Avatar movement is not done by generating this event. There is code in the heartbeat + // loop that updates avatars. // base.RequestPhysicsterseUpdate(); } + */ + _position = entprop.Position; + _orientation = entprop.Rotation; + _velocity = entprop.Velocity; + _acceleration = entprop.Acceleration; + _rotationalVelocity = entprop.RotationalVelocity; + // Avatars don't report theirr changes the usual way. Changes are checked for in the heartbeat loop. + // base.RequestPhysicsterseUpdate(); } // Called by the scene when a collision with this object is reported diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 9b28a06..23b276e 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -148,7 +148,7 @@ public sealed class BSPrim : PhysicsActor { // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID); // Undo any vehicle properties - _vehicle.ProcessTypeChange(Vehicle.TYPE_NONE); + _vehicle.ProcessTypeChange(Vehicle.TYPE_NONE, 1f); _scene.RemoveVehiclePrim(this); // just to make sure // undo any dependance with/on other objects @@ -353,7 +353,7 @@ public sealed class BSPrim : PhysicsActor } set { Vehicle type = (Vehicle)value; - _vehicle.ProcessTypeChange(type); + _vehicle.ProcessTypeChange(type, _scene.LastSimulatedTimestep); _scene.TaintedObject(delegate() { if (type == Vehicle.TYPE_NONE) @@ -371,11 +371,11 @@ public sealed class BSPrim : PhysicsActor } public override void VehicleFloatParam(int param, float value) { - _vehicle.ProcessFloatVehicleParam((Vehicle)param, value); + _vehicle.ProcessFloatVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep); } public override void VehicleVectorParam(int param, OMV.Vector3 value) { - _vehicle.ProcessVectorVehicleParam((Vehicle)param, value); + _vehicle.ProcessVectorVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep); } public override void VehicleRotationParam(int param, OMV.Quaternion rotation) { @@ -1262,78 +1262,66 @@ public sealed class BSPrim : PhysicsActor const float POSITION_TOLERANCE = 0.05f; const float ACCELERATION_TOLERANCE = 0.01f; const float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f; - const bool SHOULD_DAMP_UPDATES = false; public void UpdateProperties(EntityProperties entprop) { + /* UpdatedProperties changed = 0; - if (SHOULD_DAMP_UPDATES) + // assign to the local variables so the normal set action does not happen + // if (_position != entprop.Position) + if (!_position.ApproxEquals(entprop.Position, POSITION_TOLERANCE)) { - // assign to the local variables so the normal set action does not happen - // if (_position != entprop.Position) - if (!_position.ApproxEquals(entprop.Position, POSITION_TOLERANCE)) - { - _position = entprop.Position; - // m_log.DebugFormat("{0}: UpdateProperties: id={1}, pos = {2}", LogHeader, LocalID, _position); - changed |= UpdatedProperties.Position; - } - // if (_orientation != entprop.Rotation) - if (!_orientation.ApproxEquals(entprop.Rotation, ROTATION_TOLERANCE)) - { - _orientation = entprop.Rotation; - // m_log.DebugFormat("{0}: UpdateProperties: id={1}, rot = {2}", LogHeader, LocalID, _orientation); - changed |= UpdatedProperties.Rotation; - } - // if (_velocity != entprop.Velocity) - if (!_velocity.ApproxEquals(entprop.Velocity, VELOCITY_TOLERANCE)) - { - _velocity = entprop.Velocity; - // m_log.DebugFormat("{0}: UpdateProperties: velocity = {1}", LogHeader, _velocity); - changed |= UpdatedProperties.Velocity; - } - // if (_acceleration != entprop.Acceleration) - if (!_acceleration.ApproxEquals(entprop.Acceleration, ACCELERATION_TOLERANCE)) - { - _acceleration = entprop.Acceleration; - // m_log.DebugFormat("{0}: UpdateProperties: acceleration = {1}", LogHeader, _acceleration); - changed |= UpdatedProperties.Acceleration; - } - // if (_rotationalVelocity != entprop.RotationalVelocity) - if (!_rotationalVelocity.ApproxEquals(entprop.RotationalVelocity, ROTATIONAL_VELOCITY_TOLERANCE)) - { - _rotationalVelocity = entprop.RotationalVelocity; - // m_log.DebugFormat("{0}: UpdateProperties: rotationalVelocity = {1}", LogHeader, _rotationalVelocity); - changed |= UpdatedProperties.RotationalVel; - } - if (changed != 0) - { - // m_log.DebugFormat("{0}: UpdateProperties: id={1}, c={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation); - // Only update the position of single objects and linkset roots - if (this._parentPrim == null) - { - // m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation); - base.RequestPhysicsterseUpdate(); - } - } + _position = entprop.Position; + changed |= UpdatedProperties.Position; } - else + // if (_orientation != entprop.Rotation) + if (!_orientation.ApproxEquals(entprop.Rotation, ROTATION_TOLERANCE)) { - // Don't check for damping here -- it's done in BulletSim and SceneObjectPart. - - // Only updates only for individual prims and for the root object of a linkset. + _orientation = entprop.Rotation; + changed |= UpdatedProperties.Rotation; + } + // if (_velocity != entprop.Velocity) + if (!_velocity.ApproxEquals(entprop.Velocity, VELOCITY_TOLERANCE)) + { + _velocity = entprop.Velocity; + changed |= UpdatedProperties.Velocity; + } + // if (_acceleration != entprop.Acceleration) + if (!_acceleration.ApproxEquals(entprop.Acceleration, ACCELERATION_TOLERANCE)) + { + _acceleration = entprop.Acceleration; + changed |= UpdatedProperties.Acceleration; + } + // if (_rotationalVelocity != entprop.RotationalVelocity) + if (!_rotationalVelocity.ApproxEquals(entprop.RotationalVelocity, ROTATIONAL_VELOCITY_TOLERANCE)) + { + _rotationalVelocity = entprop.RotationalVelocity; + changed |= UpdatedProperties.RotationalVel; + } + if (changed != 0) + { + // Only update the position of single objects and linkset roots if (this._parentPrim == null) { - // Assign to the local variables so the normal set action does not happen - _position = entprop.Position; - _orientation = entprop.Rotation; - _velocity = entprop.Velocity; - _acceleration = entprop.Acceleration; - _rotationalVelocity = entprop.RotationalVelocity; - // m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}, vel={5}, acc={6}, rvel={7}", - // LogHeader, LocalID, changed, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); base.RequestPhysicsterseUpdate(); } } + */ + + // 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 (this._parentPrim == null) + { + // Assign to the local variables so the normal set action does not happen + _position = entprop.Position; + _orientation = entprop.Rotation; + _velocity = entprop.Velocity; + _acceleration = entprop.Acceleration; + _rotationalVelocity = entprop.RotationalVelocity; + // m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}, vel={5}, acc={6}, rvel={7}", + // LogHeader, LocalID, changed, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); + base.RequestPhysicsterseUpdate(); + } } // I've collided with something diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index eb1d798..150326e 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -107,6 +107,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters private long m_simulationStep = 0; public long SimulationStep { get { return m_simulationStep; } } + public float LastSimulatedTimestep { get; private set; } + // A value of the time now so all the collision and update routines do not have to get their own // Set to 'now' just before all the prims and actors are called for collisions and updates private int m_simulationNowTime; @@ -123,6 +125,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters private bool _meshSculptedPrim = true; // cause scuplted prims to get meshed private bool _forceSimplePrimMeshing = false; // if a cube or sphere, let Bullet do internal shapes + public float PID_D { get; private set; } // derivative + public float PID_P { get; private set; } // proportional + public const uint TERRAIN_ID = 0; // OpenSim senses terrain with a localID of zero public const uint GROUNDPLANE_ID = 1; @@ -222,6 +227,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters 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; @@ -278,6 +286,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters 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); @@ -415,6 +426,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters int collidersCount; IntPtr collidersPtr; + LastSimulatedTimestep = timeStep; + // prevent simulation until we've been initialized if (!m_initialized) return 10.0f; -- cgit v1.1 From e9c437ed0ecc1eb335c3704718aac068468dfb53 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 18 Jul 2012 08:35:35 -0700 Subject: Correct namespace of BinaryLoggingModule (a cut-and-paste error). Add a simple, high performance logger for high frequency logging (physics sub-operations, for instance). --- .../Statistics/Logging/BinaryLoggingModule.cs | 2 +- .../Framework/Statistics/Logging/LogWriter.cs | 161 +++++++++++++++++++++ 2 files changed, 162 insertions(+), 1 deletion(-) create mode 100755 OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/Framework/Statistics/Logging/BinaryLoggingModule.cs b/OpenSim/Region/CoreModules/Framework/Statistics/Logging/BinaryLoggingModule.cs index a75ff62..9b1b1a3 100644 --- a/OpenSim/Region/CoreModules/Framework/Statistics/Logging/BinaryLoggingModule.cs +++ b/OpenSim/Region/CoreModules/Framework/Statistics/Logging/BinaryLoggingModule.cs @@ -39,7 +39,7 @@ using OpenSim.Region.Framework; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; -namespace OpenSim.Region.CoreModules.Avatar.Attachments +namespace OpenSim.Region.CoreModules.Statistics.Logging { [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "BinaryLoggingModule")] public class BinaryLoggingModule : INonSharedRegionModule diff --git a/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs b/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs new file mode 100755 index 0000000..65e4c90 --- /dev/null +++ b/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs @@ -0,0 +1,161 @@ +/* + * 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.IO; +using System.Text; +using log4net; + +namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging +{ + /// + /// Class for writing a high performance, high volume log file. + /// Sometimes, to debug, one has a high volume logging to do and the regular + /// log file output is not appropriate. + /// Create a new instance with the parameters needed and + /// call Write() to output a line. Call Close() when finished. + /// If created with no parameters, it will not log anything. + /// + public class LogWriter : IDisposable + { + public bool Enabled { get; private set; } + + private string m_logDirectory = "."; + private int m_logMaxFileTimeMin = 5; // 5 minutes + public String LogFileHeader { get; set; } + + private StreamWriter m_logFile = null; + private TimeSpan m_logFileLife; + private DateTime m_logFileEndTime; + private Object m_logFileWriteLock = new Object(); + + // set externally when debugging. If let 'null', this does not write any error messages. + public ILog ErrorLogger = null; + private string LogHeader = "[LOG WRITER]"; + + /// + /// Create a log writer that will not write anything. Good for when not enabled + /// but the write statements are still in the code. + /// + public LogWriter() + { + Enabled = false; + m_logFile = null; + } + + /// + /// Create a log writer instance. + /// + /// The directory to create the log file in. May be 'null' for default. + /// The characters that begin the log file name. May be 'null' for default. + /// Maximum age of a log file in minutes. If zero, will set default. + public LogWriter(string dir, string headr, int maxFileTime) + { + m_logDirectory = dir == null ? "." : dir; + + LogFileHeader = headr == null ? "log-" : headr; + + m_logMaxFileTimeMin = maxFileTime; + if (m_logMaxFileTimeMin < 1) + m_logMaxFileTimeMin = 5; + + m_logFileLife = new TimeSpan(0, m_logMaxFileTimeMin, 0); + m_logFileEndTime = DateTime.Now + m_logFileLife; + + Enabled = true; + } + + public void Dispose() + { + this.Close(); + } + + public void Close() + { + Enabled = false; + if (m_logFile != null) + { + m_logFile.Close(); + m_logFile.Dispose(); + m_logFile = null; + } + } + + public void Write(string line, params object[] args) + { + if (!Enabled) return; + Write(String.Format(line, args)); + } + + public void Write(string line) + { + if (!Enabled) return; + try + { + lock (m_logFileWriteLock) + { + DateTime now = DateTime.Now; + if (m_logFile == null || now > m_logFileEndTime) + { + if (m_logFile != null) + { + m_logFile.Close(); + m_logFile.Dispose(); + m_logFile = null; + } + + // First log file or time has expired, start writing to a new log file + m_logFileEndTime = now + m_logFileLife; + string path = (m_logDirectory.Length > 0 ? m_logDirectory + + System.IO.Path.DirectorySeparatorChar.ToString() : "") + + String.Format("{0}{1}.log", LogFileHeader, now.ToString("yyyyMMddHHmmss")); + m_logFile = new StreamWriter(File.Open(path, FileMode.Append, FileAccess.Write)); + } + if (m_logFile != null) + { + StringBuilder buff = new StringBuilder(line.Length + 25); + buff.Append(now.ToString("yyyyMMddHHmmssfff")); + // buff.Append(now.ToString("yyyyMMddHHmmss")); + buff.Append(","); + buff.Append(line); + buff.Append("\r\n"); + m_logFile.Write(buff.ToString()); + } + } + } + catch (Exception e) + { + if (ErrorLogger != null) + { + ErrorLogger.ErrorFormat("{0}: FAILURE WRITING TO LOGFILE: {1}", LogHeader, e); + } + Enabled = false; + } + return; + } + } +} \ No newline at end of file -- cgit v1.1 From cda67a68de11790ff7f3f19937b4d08309bc1e89 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 18 Jul 2012 08:36:41 -0700 Subject: BulletSim: Add very detailed logging to BSDynamics for vehicle debugging --- OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | 130 ++++++++++++++------- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 1 + OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 60 +++++++++- 3 files changed, 146 insertions(+), 45 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index eb20eb3..bef7aec 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs @@ -131,8 +131,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin m_type = Vehicle.TYPE_NONE; } - internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue) + internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue, float timestep) { + DetailLog("{0},ProcessFloatVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue); switch (pParam) { case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY: @@ -229,8 +230,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin } }//end ProcessFloatVehicleParam - internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue) + internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue, float timestep) { + DetailLog("{0},ProcessVectorVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue); switch (pParam) { case Vehicle.ANGULAR_FRICTION_TIMESCALE: @@ -265,6 +267,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue) { + DetailLog("{0},ProcessRotationalVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue); switch (pParam) { case Vehicle.REFERENCE_FRAME: @@ -278,6 +281,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin internal void ProcessVehicleFlags(int pParam, bool remove) { + DetailLog("{0},ProcessVehicleFlags,param={1},remove={2}", m_prim.LocalID, pParam, remove); if (remove) { if (pParam == -1) @@ -434,6 +438,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin internal void ProcessTypeChange(Vehicle pType) { + DetailLog("{0},ProcessTypeChange,type={1}", m_prim.LocalID, pType); // Set Defaults For Type m_type = pType; switch (pType) @@ -594,7 +599,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY); m_Hoverflags |= (VehicleFlag.HOVER_GLOBAL_HEIGHT); break; - } }//end SetDefaultsForType @@ -609,12 +613,17 @@ namespace OpenSim.Region.Physics.BulletSPlugin MoveLinear(pTimestep, pParentScene); MoveAngular(pTimestep); LimitRotation(pTimestep); + DetailLog("{0},step,pos={1},force={2},velocity={3},angvel={4}", + m_prim.LocalID, m_prim.Position, m_prim.Force, m_prim.Velocity, m_prim.RotationalVelocity); }// end Step private void MoveLinear(float pTimestep, BSScene _pParentScene) { if (!m_linearMotorDirection.ApproxEquals(Vector3.Zero, 0.01f)) // requested m_linearMotorDirection is significant { + Vector3 origDir = m_linearMotorDirection; + Vector3 origVel = m_lastLinearVelocityVector; + // add drive to body Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale/pTimestep); m_lastLinearVelocityVector += (addAmount*10); // lastLinearVelocityVector is the current body velocity vector? @@ -630,9 +639,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin // decay applied velocity Vector3 decayfraction = ((Vector3.One/(m_linearMotorDecayTimescale/pTimestep))); - //Console.WriteLine("decay: " + decayfraction); m_linearMotorDirection -= m_linearMotorDirection * decayfraction * 0.5f; - //Console.WriteLine("actual: " + m_linearMotorDirection); + + DetailLog("{0},MoveLinear,nonZero,origdir={1},origvel={2},add={3},decay={4},dir={5},vel={6}", + m_prim.LocalID, origDir, origVel, addAmount, decayfraction, m_linearMotorDirection, m_lastLinearVelocityVector); } else { // requested is not significant @@ -643,63 +653,66 @@ namespace OpenSim.Region.Physics.BulletSPlugin // convert requested object velocity to world-referenced vector m_dir = m_lastLinearVelocityVector; - Quaternion rot = m_prim.Orientation; - Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); // rotq = rotation of object - m_dir *= rotq; // apply obj rotation to velocity vector + m_dir *= m_prim.Orientation; + + // Add the various forces into m_dir which will be our new direction vector (velocity) - // add Gravity andBuoyancy + // add Gravity and Buoyancy // KF: So far I have found no good method to combine a script-requested // .Z velocity and gravity. Therefore only 0g will used script-requested // .Z velocity. >0g (m_VehicleBuoyancy < 1) will used modified gravity only. Vector3 grav = Vector3.Zero; - // There is some gravity, make a gravity force vector - // that is applied after object velocity. - float objMass = m_prim.Mass; + // There is some gravity, make a gravity force vector that is applied after object velocity. // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; - grav.Z = _pParentScene.DefaultGravity.Z * objMass * (1f - m_VehicleBuoyancy); + grav.Z = _pParentScene.DefaultGravity.Z * m_prim.Mass * (1f - m_VehicleBuoyancy); // Preserve the current Z velocity Vector3 vel_now = m_prim.Velocity; m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity Vector3 pos = m_prim.Position; + Vector3 posChange = pos; // Vector3 accel = new Vector3(-(m_dir.X - m_lastLinearVelocityVector.X / 0.1f), -(m_dir.Y - m_lastLinearVelocityVector.Y / 0.1f), m_dir.Z - m_lastLinearVelocityVector.Z / 0.1f); - Vector3 posChange = new Vector3(); - posChange.X = pos.X - m_lastPositionVector.X; - posChange.Y = pos.Y - m_lastPositionVector.Y; - posChange.Z = pos.Z - m_lastPositionVector.Z; double Zchange = Math.Abs(posChange.Z); if (m_BlockingEndPoint != Vector3.Zero) { + bool changed = false; if (pos.X >= (m_BlockingEndPoint.X - (float)1)) { pos.X -= posChange.X + 1; - m_prim.Position = pos; + changed = true; } if (pos.Y >= (m_BlockingEndPoint.Y - (float)1)) { pos.Y -= posChange.Y + 1; - m_prim.Position = pos; + changed = true; } if (pos.Z >= (m_BlockingEndPoint.Z - (float)1)) { pos.Z -= posChange.Z + 1; - m_prim.Position = pos; + changed = true; } if (pos.X <= 0) { pos.X += posChange.X + 1; - m_prim.Position = pos; + changed = true; } if (pos.Y <= 0) { pos.Y += posChange.Y + 1; + changed = true; + } + if (changed) + { m_prim.Position = pos; + DetailLog("{0},MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}", + m_prim.LocalID, m_BlockingEndPoint, posChange, pos); } } if (pos.Z < _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y)) { pos.Z = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y) + 2; m_prim.Position = pos; + DetailLog("{0},MoveLinear,terrainHeight,pos={1}", m_prim.LocalID, pos); } // Check if hovering @@ -746,6 +759,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin } } + DetailLog("{0},MoveLinear,hover,pos={1},dir={2},height={3},target={4}", m_prim.LocalID, pos, m_dir, m_VhoverHeight, m_VhoverTargetHeight); + // m_VhoverEfficiency = 0f; // 0=boucy, 1=Crit.damped // m_VhoverTimescale = 0f; // time to acheive height // pTimestep is time since last frame,in secs @@ -774,12 +789,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin { grav.Z = (float)(grav.Z * 1.125); } - float terraintemp = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y); + float terraintemp = _pParentScene.GetTerrainHeightAtXYZ(pos); float postemp = (pos.Z - terraintemp); if (postemp > 2.5f) { grav.Z = (float)(grav.Z * 1.037125); } + DetailLog("{0},MoveLinear,limitMotorUp,grav={1}", m_prim.LocalID, grav); //End Experimental Values } if ((m_flags & (VehicleFlag.NO_X)) != 0) @@ -803,29 +819,35 @@ namespace OpenSim.Region.Physics.BulletSPlugin m_prim.Force = grav; - // apply friction + // Apply friction Vector3 decayamount = Vector3.One / (m_linearFrictionTimescale / pTimestep); m_lastLinearVelocityVector -= m_lastLinearVelocityVector * decayamount; + + DetailLog("{0},MoveLinear,done,pos={1},vel={2},force={3},decay={4}", + m_prim.LocalID, m_lastPositionVector, m_dir, grav, decayamount); + } // end MoveLinear() private void MoveAngular(float pTimestep) { - /* - private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor - private int m_angularMotorApply = 0; // application frame counter - private float m_angularMotorVelocity = 0; // current angular motor velocity (ramps up and down) - private float m_angularMotorTimescale = 0; // motor angular velocity ramp up rate - private float m_angularMotorDecayTimescale = 0; // motor angular velocity decay rate - private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate - private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body - */ + // m_angularMotorDirection // angular velocity requested by LSL motor + // m_angularMotorApply // application frame counter + // m_angularMotorVelocity // current angular motor velocity (ramps up and down) + // m_angularMotorTimescale // motor angular velocity ramp up rate + // m_angularMotorDecayTimescale // motor angular velocity decay rate + // m_angularFrictionTimescale // body angular velocity decay rate + // m_lastAngularVelocity // what was last applied to body // Get what the body is doing, this includes 'external' influences Vector3 angularVelocity = m_prim.RotationalVelocity; - // Vector3 angularVelocity = Vector3.Zero; if (m_angularMotorApply > 0) { + // Rather than snapping the angular motor velocity from the old value to + // a newly set velocity, this routine steps the value from the previous + // value (m_angularMotorVelocity) to the requested value (m_angularMotorDirection). + // There are m_angularMotorApply steps. + Vector3 origAngularVelocity = m_angularMotorVelocity; // ramp up to new value // current velocity += error / (time to get there / step interval) // requested speed - last motor speed @@ -833,23 +855,21 @@ namespace OpenSim.Region.Physics.BulletSPlugin m_angularMotorVelocity.Y += (m_angularMotorDirection.Y - m_angularMotorVelocity.Y) / (m_angularMotorTimescale / pTimestep); m_angularMotorVelocity.Z += (m_angularMotorDirection.Z - m_angularMotorVelocity.Z) / (m_angularMotorTimescale / pTimestep); + DetailLog("{0},MoveAngular,angularMotorApply,apply={1},origvel={2},dir={3},vel={4}", + m_prim.LocalID,m_angularMotorApply,origAngularVelocity, m_angularMotorDirection, m_angularMotorVelocity); + m_angularMotorApply--; // This is done so that if script request rate is less than phys frame rate the expected // velocity may still be acheived. } else { - // no motor recently applied, keep the body velocity - /* m_angularMotorVelocity.X = angularVelocity.X; - m_angularMotorVelocity.Y = angularVelocity.Y; - m_angularMotorVelocity.Z = angularVelocity.Z; */ - + // No motor recently applied, keep the body velocity // and decay the velocity m_angularMotorVelocity -= m_angularMotorVelocity / (m_angularMotorDecayTimescale / pTimestep); } // end motor section // Vertical attractor section Vector3 vertattr = Vector3.Zero; - if (m_verticalAttractionTimescale < 300) { float VAservo = 0.2f / (m_verticalAttractionTimescale * pTimestep); @@ -871,7 +891,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin // Error is 0 (no error) to +/- 2 (max error) // scale it by VAservo verterr = verterr * VAservo; -//if (frcount == 0) Console.WriteLine("VAerr=" + verterr); // As the body rotates around the X axis, then verterr.Y increases; Rotated around Y then .X increases, so // Change Body angular velocity X based on Y, and Y based on X. Z is not changed. @@ -884,11 +903,15 @@ namespace OpenSim.Region.Physics.BulletSPlugin vertattr.X += bounce * angularVelocity.X; vertattr.Y += bounce * angularVelocity.Y; + DetailLog("{0},MoveAngular,verticalAttraction,verterr={1},bounce={2},vertattr={3}", + m_prim.LocalID, verterr, bounce, vertattr); + } // else vertical attractor is off - // m_lastVertAttractor = vertattr; + // m_lastVertAttractor = vertattr; // Bank section tba + // Deflection section tba // Sum velocities @@ -898,11 +921,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin { m_lastAngularVelocity.X = 0; m_lastAngularVelocity.Y = 0; + DetailLog("{0},MoveAngular,noDeflectionUp,lastAngular={1}", m_prim.LocalID, m_lastAngularVelocity); } if (m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f)) { m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero. + DetailLog("{0},MoveAngular,zeroSmallValues,lastAngular={1}", m_prim.LocalID, m_lastAngularVelocity); } // apply friction @@ -912,10 +937,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin // Apply to the body m_prim.RotationalVelocity = m_lastAngularVelocity; + DetailLog("{0},MoveAngular,done,decay={1},lastAngular={2}", m_prim.LocalID, decayamount, m_lastAngularVelocity); + } //end MoveAngular + } //end MoveAngular internal void LimitRotation(float timestep) { - Quaternion rotq = m_prim.Orientation; // rotq = rotation of object + Quaternion rotq = m_prim.Orientation; Quaternion m_rot = rotq; bool changed = false; if (m_RollreferenceFrame != Quaternion.Identity) @@ -923,18 +951,22 @@ namespace OpenSim.Region.Physics.BulletSPlugin if (rotq.X >= m_RollreferenceFrame.X) { m_rot.X = rotq.X - (m_RollreferenceFrame.X / 2); + changed = true; } if (rotq.Y >= m_RollreferenceFrame.Y) { m_rot.Y = rotq.Y - (m_RollreferenceFrame.Y / 2); + changed = true; } if (rotq.X <= -m_RollreferenceFrame.X) { m_rot.X = rotq.X + (m_RollreferenceFrame.X / 2); + changed = true; } if (rotq.Y <= -m_RollreferenceFrame.Y) { m_rot.Y = rotq.Y + (m_RollreferenceFrame.Y / 2); + changed = true; } changed = true; } @@ -944,8 +976,22 @@ namespace OpenSim.Region.Physics.BulletSPlugin m_rot.Y = 0; changed = true; } + if ((m_flags & VehicleFlag.LOCK_ROTATION) != 0) + { + m_rot.X = 0; + m_rot.Y = 0; + changed = true; + } if (changed) m_prim.Orientation = m_rot; + + DetailLog("{0},LimitRotation,done,changed={1},orig={2},new={3}", m_prim.LocalID, changed, rotq, m_rot); + } + + // Invoke the detailed logger and output something if it's enabled. + private void DetailLog(string msg, params Object[] args) + { + m_prim.Scene.VehicleLogging.Write(msg, args); } } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 23b276e..227696e 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -52,6 +52,7 @@ public sealed class BSPrim : PhysicsActor private List _hulls; private BSScene _scene; + public BSScene Scene { get { return _scene; } } private String _avName; private uint _localID = 0; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 150326e..c4b4332 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -29,12 +29,13 @@ using System.Collections.Generic; using System.Runtime.InteropServices; using System.Text; using System.Threading; -using Nini.Config; -using log4net; using OpenSim.Framework; +using OpenSim.Region.CoreModules.Framework.Statistics.Logging; +using OpenSim.Region.Framework; using OpenSim.Region.Physics.Manager; +using Nini.Config; +using log4net; using OpenMetaverse; -using OpenSim.Region.Framework; // TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim) // Debug linkset @@ -158,6 +159,19 @@ public class BSScene : PhysicsScene, IPhysicsParameters private BulletSimAPI.DebugLogCallback m_DebugLogCallbackHandle; + // Sometimes you just have to log everything. + public LogWriter PhysicsLogging; + private bool m_physicsLoggingEnabled; + private string m_physicsLoggingDir; + private string m_physicsLoggingPrefix; + private int m_physicsLoggingFileMinutes; + + public LogWriter VehicleLogging; + private bool m_vehicleLoggingEnabled; + private string m_vehicleLoggingDir; + private string m_vehicleLoggingPrefix; + private int m_vehicleLoggingFileMinutes; + public BSScene(string identifier) { m_initialized = false; @@ -178,6 +192,26 @@ public class BSScene : PhysicsScene, IPhysicsParameters m_updateArray = new EntityProperties[m_maxUpdatesPerFrame]; m_updateArrayPinnedHandle = GCHandle.Alloc(m_updateArray, GCHandleType.Pinned); + // Enable very detailed logging. + // By creating an empty logger when not logging, the log message invocation code + // can be left in and every call doesn't have to check for null. + if (m_physicsLoggingEnabled) + { + PhysicsLogging = new LogWriter(m_physicsLoggingDir, m_physicsLoggingPrefix, m_physicsLoggingFileMinutes); + } + else + { + PhysicsLogging = new LogWriter(); + } + if (m_vehicleLoggingEnabled) + { + VehicleLogging = new LogWriter(m_vehicleLoggingDir, m_vehicleLoggingPrefix, m_vehicleLoggingFileMinutes); + } + else + { + VehicleLogging = new LogWriter(); + } + // Get the version of the DLL // TODO: this doesn't work yet. Something wrong with marshaling the returned string. // BulletSimVersion = BulletSimAPI.GetVersion(); @@ -321,6 +355,17 @@ public class BSScene : PhysicsScene, IPhysicsParameters parms.shouldSplitSimulationIslands = ParamBoolean(pConfig, "ShouldSplitSimulationIslands", parms.shouldSplitSimulationIslands); parms.shouldEnableFrictionCaching = ParamBoolean(pConfig, "ShouldEnableFrictionCaching", parms.shouldEnableFrictionCaching); parms.numberOfSolverIterations = pConfig.GetFloat("NumberOfSolverIterations", parms.numberOfSolverIterations); + + // Very detailed logging for physics debugging + m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false); + m_physicsLoggingDir = pConfig.GetString("PhysicsLoggingDir", "."); + m_physicsLoggingPrefix = pConfig.GetString("PhysicsLoggingPrefix", "physics-"); + m_physicsLoggingFileMinutes = pConfig.GetInt("PhysicsLoggingFileMinutes", 5); + // Very detailed logging for vehicle debugging + m_vehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false); + m_vehicleLoggingDir = pConfig.GetString("VehicleLoggingDir", "."); + m_vehicleLoggingPrefix = pConfig.GetString("VehicleLoggingPrefix", "vehicle-"); + m_vehicleLoggingFileMinutes = pConfig.GetInt("VehicleLoggingFileMinutes", 5); } } m_params[0] = parms; @@ -560,8 +605,17 @@ public class BSScene : PhysicsScene, IPhysicsParameters }); } + // Someday we will have complex terrain with caves and tunnels + // For the moment, it's flat and convex + public float GetTerrainHeightAtXYZ(Vector3 loc) + { + return GetTerrainHeightAtXY(loc.X, loc.Y); + } + public float GetTerrainHeightAtXY(float tX, float tY) { + if (tX < 0 || tX >= Constants.RegionSize || tY < 0 || tY >= Constants.RegionSize) + return 30; return m_heightMap[((int)tX) * Constants.RegionSize + ((int)tY)]; } -- cgit v1.1 From 7451bb16137fad6336fae12608ef6df92ba1a46c Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 18 Jul 2012 08:49:01 -0700 Subject: BulletSim: fix compile errors from last commit. Clean up passing of physics scene into vehicle dynamics code. --- OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | 23 +++++++++++----------- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 6 +++--- 2 files changed, 14 insertions(+), 15 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index bef7aec..4c5bc85 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs @@ -57,7 +57,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin private int frcount = 0; // Used to limit dynamics debug output to // every 100th frame - // private BSScene m_parentScene = null; private BSPrim m_prim; // the prim this dynamic controller belongs to // Vehicle properties @@ -602,7 +601,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin } }//end SetDefaultsForType - internal void Step(float pTimestep, BSScene pParentScene) + internal void Step(float pTimestep) { if (m_type == Vehicle.TYPE_NONE) return; @@ -610,14 +609,15 @@ namespace OpenSim.Region.Physics.BulletSPlugin if (frcount > 100) frcount = 0; - MoveLinear(pTimestep, pParentScene); + MoveLinear(pTimestep); MoveAngular(pTimestep); LimitRotation(pTimestep); - DetailLog("{0},step,pos={1},force={2},velocity={3},angvel={4}", + + DetailLog("{0},step,done,pos={1},force={2},velocity={3},angvel={4}", m_prim.LocalID, m_prim.Position, m_prim.Force, m_prim.Velocity, m_prim.RotationalVelocity); }// end Step - private void MoveLinear(float pTimestep, BSScene _pParentScene) + private void MoveLinear(float pTimestep) { if (!m_linearMotorDirection.ApproxEquals(Vector3.Zero, 0.01f)) // requested m_linearMotorDirection is significant { @@ -664,7 +664,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin Vector3 grav = Vector3.Zero; // There is some gravity, make a gravity force vector that is applied after object velocity. // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; - grav.Z = _pParentScene.DefaultGravity.Z * m_prim.Mass * (1f - m_VehicleBuoyancy); + grav.Z = m_prim.Scene.DefaultGravity.Z * m_prim.Mass * (1f - m_VehicleBuoyancy); // Preserve the current Z velocity Vector3 vel_now = m_prim.Velocity; m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity @@ -708,9 +708,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin m_prim.LocalID, m_BlockingEndPoint, posChange, pos); } } - if (pos.Z < _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y)) + if (pos.Z < m_prim.Scene.GetTerrainHeightAtXY(pos.X, pos.Y)) { - pos.Z = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y) + 2; + pos.Z = m_prim.Scene.GetTerrainHeightAtXY(pos.X, pos.Y) + 2; m_prim.Position = pos; DetailLog("{0},MoveLinear,terrainHeight,pos={1}", m_prim.LocalID, pos); } @@ -721,11 +721,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin // We should hover, get the target height if ((m_Hoverflags & VehicleFlag.HOVER_WATER_ONLY) != 0) { - m_VhoverTargetHeight = _pParentScene.GetWaterLevel() + m_VhoverHeight; + m_VhoverTargetHeight = m_prim.Scene.GetWaterLevel() + m_VhoverHeight; } if ((m_Hoverflags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0) { - m_VhoverTargetHeight = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight; + m_VhoverTargetHeight = m_prim.Scene.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight; } if ((m_Hoverflags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0) { @@ -789,7 +789,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin { grav.Z = (float)(grav.Z * 1.125); } - float terraintemp = _pParentScene.GetTerrainHeightAtXYZ(pos); + float terraintemp = m_prim.Scene.GetTerrainHeightAtXYZ(pos); float postemp = (pos.Z - terraintemp); if (postemp > 2.5f) { @@ -940,7 +940,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin DetailLog("{0},MoveAngular,done,decay={1},lastAngular={2}", m_prim.LocalID, decayamount, m_lastAngularVelocity); } //end MoveAngular - } //end MoveAngular internal void LimitRotation(float timestep) { Quaternion rotq = m_prim.Orientation; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 227696e..5911897 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -149,7 +149,7 @@ public sealed class BSPrim : PhysicsActor { // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID); // Undo any vehicle properties - _vehicle.ProcessTypeChange(Vehicle.TYPE_NONE, 1f); + _vehicle.ProcessTypeChange(Vehicle.TYPE_NONE); _scene.RemoveVehiclePrim(this); // just to make sure // undo any dependance with/on other objects @@ -354,7 +354,7 @@ public sealed class BSPrim : PhysicsActor } set { Vehicle type = (Vehicle)value; - _vehicle.ProcessTypeChange(type, _scene.LastSimulatedTimestep); + _vehicle.ProcessTypeChange(type); _scene.TaintedObject(delegate() { if (type == Vehicle.TYPE_NONE) @@ -389,7 +389,7 @@ public sealed class BSPrim : PhysicsActor // Called each simulation step to advance vehicle characteristics public void StepVehicle(float timeStep) { - _vehicle.Step(timeStep, _scene); + _vehicle.Step(timeStep); } // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more -- cgit v1.1 From ca3b6b1f90f89ab3be4a43863da81f9df0993e2f Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 20 Jul 2012 14:08:29 -0700 Subject: BulletSim: more detail logging for vehicle and general physics debugging. Physical linksets are fully functional. Tweeking of the vehicle code to make it semi-work. Utilize the new API2 for some setting operations. Add GetOrientation() API call for proper reporting of children of linksets. Changes the interface between C# and C++ code so old DLLs won't work! --- OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | 52 +++++-- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 168 +++++++++++++++++---- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 48 +++--- .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 51 +++++++ 4 files changed, 244 insertions(+), 75 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index 4c5bc85..c197e61 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs @@ -613,23 +613,30 @@ namespace OpenSim.Region.Physics.BulletSPlugin MoveAngular(pTimestep); LimitRotation(pTimestep); - DetailLog("{0},step,done,pos={1},force={2},velocity={3},angvel={4}", + DetailLog("{0},Dynamics,done,pos={1},force={2},velocity={3},angvel={4}", m_prim.LocalID, m_prim.Position, m_prim.Force, m_prim.Velocity, m_prim.RotationalVelocity); }// end Step private void MoveLinear(float pTimestep) { - if (!m_linearMotorDirection.ApproxEquals(Vector3.Zero, 0.01f)) // requested m_linearMotorDirection is significant + // requested m_linearMotorDirection is significant + // if (!m_linearMotorDirection.ApproxEquals(Vector3.Zero, 0.01f)) + if (m_linearMotorDirection.LengthSquared() > 0.0001f) { Vector3 origDir = m_linearMotorDirection; Vector3 origVel = m_lastLinearVelocityVector; // add drive to body - Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale/pTimestep); - m_lastLinearVelocityVector += (addAmount*10); // lastLinearVelocityVector is the current body velocity vector? + // Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale/pTimestep); + Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale); + // lastLinearVelocityVector is the current body velocity vector? + // RA: Not sure what the *10 is for. A correction for pTimestep? + // m_lastLinearVelocityVector += (addAmount*10); + m_lastLinearVelocityVector += addAmount; // This will work temporarily, but we really need to compare speed on an axis // KF: Limit body velocity to applied velocity? + // Limit the velocity vector to less than the last set linear motor direction if (Math.Abs(m_lastLinearVelocityVector.X) > Math.Abs(m_linearMotorDirectionLASTSET.X)) m_lastLinearVelocityVector.X = m_linearMotorDirectionLASTSET.X; if (Math.Abs(m_lastLinearVelocityVector.Y) > Math.Abs(m_linearMotorDirectionLASTSET.Y)) @@ -641,19 +648,30 @@ namespace OpenSim.Region.Physics.BulletSPlugin Vector3 decayfraction = ((Vector3.One/(m_linearMotorDecayTimescale/pTimestep))); m_linearMotorDirection -= m_linearMotorDirection * decayfraction * 0.5f; + /* + Vector3 addAmount = (m_linearMotorDirection - m_lastLinearVelocityVector)/m_linearMotorTimescale; + m_lastLinearVelocityVector += addAmount; + + float decayfraction = (1.0f - 1.0f / m_linearMotorDecayTimescale); + m_linearMotorDirection *= decayfraction; + + */ + DetailLog("{0},MoveLinear,nonZero,origdir={1},origvel={2},add={3},decay={4},dir={5},vel={6}", m_prim.LocalID, origDir, origVel, addAmount, decayfraction, m_linearMotorDirection, m_lastLinearVelocityVector); } else - { // requested is not significant - // if what remains of applied is small, zero it. - if (m_lastLinearVelocityVector.ApproxEquals(Vector3.Zero, 0.01f)) - m_lastLinearVelocityVector = Vector3.Zero; + { + // if what remains of applied is small, zero it. + // if (m_lastLinearVelocityVector.ApproxEquals(Vector3.Zero, 0.01f)) + // m_lastLinearVelocityVector = Vector3.Zero; + m_linearMotorDirection = Vector3.Zero; + m_lastLinearVelocityVector = Vector3.Zero; } // convert requested object velocity to world-referenced vector - m_dir = m_lastLinearVelocityVector; - m_dir *= m_prim.Orientation; + Quaternion rotq = m_prim.Orientation; + m_dir = m_lastLinearVelocityVector * rotq; // Add the various forces into m_dir which will be our new direction vector (velocity) @@ -708,9 +726,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin m_prim.LocalID, m_BlockingEndPoint, posChange, pos); } } - if (pos.Z < m_prim.Scene.GetTerrainHeightAtXY(pos.X, pos.Y)) + + // If below the terrain, move us above the ground a little. + if (pos.Z < m_prim.Scene.GetTerrainHeightAtXYZ(pos)) { - pos.Z = m_prim.Scene.GetTerrainHeightAtXY(pos.X, pos.Y) + 2; + pos.Z = m_prim.Scene.GetTerrainHeightAtXYZ(pos) + 2; m_prim.Position = pos; DetailLog("{0},MoveLinear,terrainHeight,pos={1}", m_prim.LocalID, pos); } @@ -816,8 +836,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin // Apply velocity m_prim.Velocity = m_dir; // apply gravity force - m_prim.Force = grav; - + // Why is this set here? The physics engine already does gravity. + // m_prim.AddForce(grav, false); + // m_prim.Force = grav; // Apply friction Vector3 decayamount = Vector3.One / (m_linearFrictionTimescale / pTimestep); @@ -990,7 +1011,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin // Invoke the detailed logger and output something if it's enabled. private void DetailLog(string msg, params Object[] args) { - m_prim.Scene.VehicleLogging.Write(msg, args); + if (m_prim.Scene.VehicleLoggingEnabled) + m_prim.Scene.PhysicsLogging.Write(msg, args); } } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 5911897..71a4303 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -148,6 +148,7 @@ public sealed class BSPrim : PhysicsActor public void Destroy() { // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID); + // DetailLog("{0},Destroy", LocalID); // Undo any vehicle properties _vehicle.ProcessTypeChange(Vehicle.TYPE_NONE); _scene.RemoveVehiclePrim(this); // just to make sure @@ -215,6 +216,7 @@ public sealed class BSPrim : PhysicsActor public override void link(PhysicsActor obj) { 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) { @@ -250,6 +252,7 @@ public sealed class BSPrim : PhysicsActor // 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); @@ -266,6 +269,7 @@ public sealed class BSPrim : PhysicsActor 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 @@ -284,6 +288,7 @@ public sealed class BSPrim : PhysicsActor if (_childrenPrims.Contains(child)) { DebugLog("{0}: RemoveChildFromLinkset: Removing constraint to {1}", LogHeader, child.LocalID); + DetailLog("{0},RemoveChildToLinkset,child={1}", LocalID, pchild.LocalID); if (!BulletSimAPI.RemoveConstraintByID(_scene.WorldID, child.LocalID)) { m_log.ErrorFormat("{0}: RemoveChildFromLinkset: Failed remove constraint for {1}", LogHeader, child.LocalID); @@ -317,20 +322,28 @@ public sealed class BSPrim : PhysicsActor base.RequestPhysicsterseUpdate(); } - public override void LockAngularMotion(OMV.Vector3 axis) { return; } + public override void LockAngularMotion(OMV.Vector3 axis) + { + DetailLog("{0},LockAngularMotion,call,axis={1}", LocalID, axis); + return; + } public override OMV.Vector3 Position { get { - // don't do the following GetObjectPosition because this function is called a zillion times + // child prims move around based on their parent. Need to get the latest location + if (_parentPrim != null) + _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; } set { _position = value; + // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint? _scene.TaintedObject(delegate() { + DetailLog("{0},SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); - // m_log.DebugFormat("{0}: setPosition: id={1}, position={2}", LogHeader, _localID, _position); }); } } @@ -343,6 +356,7 @@ public sealed class BSPrim : PhysicsActor _force = value; _scene.TaintedObject(delegate() { + DetailLog("{0},SetForce,taint,force={1}", LocalID, _force); BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force); }); } @@ -354,15 +368,23 @@ public sealed class BSPrim : PhysicsActor } set { Vehicle type = (Vehicle)value; - _vehicle.ProcessTypeChange(type); _scene.TaintedObject(delegate() { + DetailLog("{0},SetVehicleType,taint,type={1}", LocalID, type); + _vehicle.ProcessTypeChange(type); if (type == Vehicle.TYPE_NONE) { _scene.RemoveVehiclePrim(this); } else { + _scene.TaintedObject(delegate() + { + // Tell the physics engine to clear state + IntPtr obj = BulletSimAPI.GetBodyHandleWorldID2(_scene.WorldID, LocalID); + BulletSimAPI.ClearForces2(obj); + }); + // make it so the scene will call us each tick to do vehicle things _scene.AddVehiclePrim(this); } @@ -372,21 +394,39 @@ public sealed class BSPrim : PhysicsActor } public override void VehicleFloatParam(int param, float value) { - _vehicle.ProcessFloatVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep); + m_log.DebugFormat("{0} VehicleFloatParam. {1} <= {2}", LogHeader, param, value); + _scene.TaintedObject(delegate() + { + _vehicle.ProcessFloatVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep); + }); } public override void VehicleVectorParam(int param, OMV.Vector3 value) { - _vehicle.ProcessVectorVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep); + m_log.DebugFormat("{0} VehicleVectorParam. {1} <= {2}", LogHeader, param, value); + _scene.TaintedObject(delegate() + { + _vehicle.ProcessVectorVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep); + }); } public override void VehicleRotationParam(int param, OMV.Quaternion rotation) { - _vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation); + m_log.DebugFormat("{0} VehicleRotationParam. {1} <= {2}", LogHeader, param, rotation); + _scene.TaintedObject(delegate() + { + _vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation); + }); } public override void VehicleFlags(int param, bool remove) { - _vehicle.ProcessVehicleFlags(param, remove); + m_log.DebugFormat("{0} VehicleFlags. {1}. Remove={2}", LogHeader, param, remove); + _scene.TaintedObject(delegate() + { + _vehicle.ProcessVehicleFlags(param, remove); + }); } - // Called each simulation step to advance vehicle characteristics + + // Called each simulation step to advance vehicle characteristics. + // Called from Scene when doing simulation step so we're in taint processing time. public void StepVehicle(float timeStep) { _vehicle.Step(timeStep); @@ -395,14 +435,11 @@ public sealed class BSPrim : PhysicsActor // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more public override void SetVolumeDetect(int param) { bool newValue = (param != 0); - if (_isVolumeDetect != newValue) + _isVolumeDetect = newValue; + _scene.TaintedObject(delegate() { - _isVolumeDetect = newValue; - _scene.TaintedObject(delegate() - { - SetObjectDynamic(); - }); - } + SetObjectDynamic(); + }); return; } @@ -410,9 +447,11 @@ public sealed class BSPrim : PhysicsActor public override OMV.Vector3 CenterOfMass { get { return OMV.Vector3.Zero; } } public override OMV.Vector3 Velocity { get { return _velocity; } - set { _velocity = value; + set { + _velocity = value; _scene.TaintedObject(delegate() { + DetailLog("{0},SetVelocity,taint,vel={1}", LocalID, _velocity); BulletSimAPI.SetObjectVelocity(_scene.WorldID, LocalID, _velocity); }); } @@ -420,6 +459,7 @@ public sealed class BSPrim : PhysicsActor public override OMV.Vector3 Torque { get { return _torque; } set { _torque = value; + DetailLog("{0},SetTorque,call,torque={1}", LocalID, _torque); } } public override float CollisionScore { @@ -432,13 +472,21 @@ public sealed class BSPrim : PhysicsActor set { _acceleration = value; } } public override OMV.Quaternion Orientation { - get { return _orientation; } + get { + if (_parentPrim != null) + { + // children move around because tied to parent. Get a fresh value. + _orientation = BulletSimAPI.GetObjectOrientation(_scene.WorldID, LocalID); + } + return _orientation; + } set { _orientation = value; - // m_log.DebugFormat("{0}: set orientation: id={1}, ori={2}", LogHeader, LocalID, _orientation); + // TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint? _scene.TaintedObject(delegate() { // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); + DetailLog("{0},SetOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation); BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); }); } @@ -471,8 +519,9 @@ public sealed class BSPrim : PhysicsActor get { return !IsPhantom && !_isVolumeDetect; } } - // make gravity work if the object is physical and not selected - // no locking here because only called when it is safe + // Make gravity work if the object is physical and not selected + // No locking here because only called when it is safe + // Only called at taint time so it is save to call into Bullet. private void SetObjectDynamic() { // m_log.DebugFormat("{0}: ID={1}, SetObjectDynamic: IsStatic={2}, IsSolid={3}", LogHeader, _localID, IsStatic, IsSolid); @@ -489,6 +538,7 @@ public sealed class BSPrim : PhysicsActor RecreateGeomAndObject(); } + DetailLog("{0},SetObjectDynamic,taint,static={1},solid={2},mass={3}", LocalID, IsStatic, IsSolid, _mass); BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), _mass); } @@ -529,11 +579,24 @@ public sealed class BSPrim : PhysicsActor set { _floatOnWater = value; } } public override OMV.Vector3 RotationalVelocity { - get { return _rotationalVelocity; } - set { _rotationalVelocity = value; + get { + /* + OMV.Vector3 pv = OMV.Vector3.Zero; + // if close to zero, report zero + // This is copied from ODE but I'm not sure why it returns zero but doesn't + // zero the property in the physics engine. + if (_rotationalVelocity.ApproxEquals(pv, 0.2f)) + return pv; + */ + + return _rotationalVelocity; + } + set { + _rotationalVelocity = value; // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); _scene.TaintedObject(delegate() { + DetailLog("{0},SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); BulletSimAPI.SetObjectAngularVelocity(_scene.WorldID, LocalID, _rotationalVelocity); }); } @@ -546,11 +609,13 @@ public sealed class BSPrim : PhysicsActor } public override float Buoyancy { get { return _buoyancy; } - set { _buoyancy = value; - _scene.TaintedObject(delegate() - { - BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy); - }); + set { + _buoyancy = value; + _scene.TaintedObject(delegate() + { + DetailLog("{0},SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy); + BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy); + }); } } @@ -586,27 +651,45 @@ public sealed class BSPrim : PhysicsActor public override float APIDStrength { set { return; } } public override float APIDDamping { set { return; } } + private List m_accumulatedForces = new List(); public override void AddForce(OMV.Vector3 force, bool pushforce) { if (force.IsFinite()) { - _force.X += force.X; - _force.Y += force.Y; - _force.Z += force.Z; + // _force += force; + lock (m_accumulatedForces) + m_accumulatedForces.Add(new OMV.Vector3(force)); } else { m_log.WarnFormat("{0}: Got a NaN force applied to a Character", LogHeader); + return; } _scene.TaintedObject(delegate() { - BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force); + lock (m_accumulatedForces) + { + if (m_accumulatedForces.Count > 0) + { + OMV.Vector3 fSum = OMV.Vector3.Zero; + foreach (OMV.Vector3 v in m_accumulatedForces) + { + fSum += v; + } + m_accumulatedForces.Clear(); + + DetailLog("{0},SetObjectForce,taint,force={1}", LocalID, fSum); + BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, fSum); + } + } }); } public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { + DetailLog("{0},AddAngularForce,call,angForce={1},push={2}", LocalID, force, pushforce); // m_log.DebugFormat("{0}: AddAngularForce. f={1}, push={2}", LogHeader, force, pushforce); } public override void SetMomentum(OMV.Vector3 momentum) { + DetailLog("{0},SetMomentum,call,mom={1}", LocalID, momentum); } public override void SubscribeEvents(int ms) { _subscribedEventsMs = ms; @@ -931,6 +1014,7 @@ public sealed class BSPrim : PhysicsActor { // 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; } @@ -938,6 +1022,7 @@ public sealed class BSPrim : PhysicsActor 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; } @@ -974,10 +1059,12 @@ public sealed class BSPrim : PhysicsActor // if this new shape is the same as last time, don't recreate the mesh if (_meshKey == newMeshKey) return; + DetailLog("{0},CreateGeomMesh,create,key={1}", LocalID, _meshKey); // Since we're recreating new, get rid of any previously generated shape if (_meshKey != 0) { // m_log.DebugFormat("{0}: CreateGeom: deleting old mesh. lID={1}, Key={2}", LogHeader, _localID, _meshKey); + DetailLog("{0},CreateGeomMesh,deleteOld,key={1}", LocalID, _meshKey); BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey); _mesh = null; _meshKey = 0; @@ -1007,6 +1094,7 @@ public sealed class BSPrim : PhysicsActor _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH; // meshes are already scaled by the meshmerizer _scale = new OMV.Vector3(1f, 1f, 1f); + DetailLog("{0},CreateGeomMesh,done", LocalID); return; } @@ -1020,13 +1108,17 @@ public sealed class BSPrim : PhysicsActor // if the hull hasn't changed, don't rebuild it if (newHullKey == _hullKey) return; + DetailLog("{0},CreateGeomHull,create,key={1}", LocalID, _meshKey); + // Since we're recreating new, get rid of any previously generated shape if (_hullKey != 0) { // m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _hullKey); + DetailLog("{0},CreateGeomHull,deleteOldHull,key={1}", LocalID, _meshKey); BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey); _hullKey = 0; _hulls.Clear(); + DetailLog("{0},CreateGeomHull,deleteOldMesh,key={1}", LocalID, _meshKey); BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey); _mesh = null; // the mesh cannot match either _meshKey = 0; @@ -1123,6 +1215,7 @@ public sealed class BSPrim : PhysicsActor _shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL; // meshes are already scaled by the meshmerizer _scale = new OMV.Vector3(1f, 1f, 1f); + DetailLog("{0},CreateGeomHull,done", LocalID); return; } @@ -1310,6 +1403,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 (this._parentPrim == null) { @@ -1319,8 +1413,12 @@ public sealed class BSPrim : PhysicsActor _velocity = entprop.Velocity; _acceleration = entprop.Acceleration; _rotationalVelocity = entprop.RotationalVelocity; + // m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}, vel={5}, acc={6}, rvel={7}", // LogHeader, LocalID, changed, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); + DetailLog("{0},UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", + LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); + base.RequestPhysicsterseUpdate(); } } @@ -1361,5 +1459,11 @@ public sealed class BSPrim : PhysicsActor collisionCollection.Clear(); } } + + // Invoke the detailed logger and output something if it's enabled. + private void DetailLog(string msg, params Object[] args) + { + Scene.PhysicsLogging.Write(msg, args); + } } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index c4b4332..9d41ce8 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -30,9 +30,9 @@ using System.Runtime.InteropServices; using System.Text; using System.Threading; using OpenSim.Framework; -using OpenSim.Region.CoreModules.Framework.Statistics.Logging; using OpenSim.Region.Framework; using OpenSim.Region.Physics.Manager; +using Logging = OpenSim.Region.CoreModules.Framework.Statistics.Logging; using Nini.Config; using log4net; using OpenMetaverse; @@ -45,15 +45,17 @@ using OpenMetaverse; // Compute physics FPS reasonably // Based on material, set density and friction // More efficient memory usage when passing hull information from BSPrim to BulletSim +// Move all logic out of the C++ code and into the C# code for easier future modifications. // Four states of prim: Physical, regular, phantom and selected. Are we modeling these correctly? // In SL one can set both physical and phantom (gravity, does not effect others, makes collisions with ground) // At the moment, physical and phantom causes object to drop through the terrain // Physical phantom objects and related typing (collision options ) +// Use collision masks for collision with terrain and phantom objects // Check out llVolumeDetect. Must do something for that. // Should prim.link() and prim.delink() membership checking happen at taint time? +// changing the position and orientation of a linked prim must rebuild the constraint with the root. // Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once // Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect -// Use collision masks for collision with terrain and phantom objects // Implement the genCollisions feature in BulletSim::SetObjectProperties (don't pass up unneeded collisions) // Implement LockAngularMotion // Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation) @@ -61,9 +63,6 @@ using OpenMetaverse; // Remove mesh and Hull stuff. Use mesh passed to bullet and use convexdecom from bullet. // Add PID movement operations. What does ScenePresence.MoveToTarget do? // Check terrain size. 128 or 127? -// Multiple contact points on collision? -// See code in ode::near... calls to collision_accounting_events() -// (This might not be a problem. ODE collects all the collisions with one object in one tick.) // Raycast // namespace OpenSim.Region.Physics.BulletSPlugin @@ -160,17 +159,14 @@ public class BSScene : PhysicsScene, IPhysicsParameters private BulletSimAPI.DebugLogCallback m_DebugLogCallbackHandle; // Sometimes you just have to log everything. - public LogWriter PhysicsLogging; + public Logging.LogWriter PhysicsLogging; private bool m_physicsLoggingEnabled; private string m_physicsLoggingDir; private string m_physicsLoggingPrefix; private int m_physicsLoggingFileMinutes; - public LogWriter VehicleLogging; private bool m_vehicleLoggingEnabled; - private string m_vehicleLoggingDir; - private string m_vehicleLoggingPrefix; - private int m_vehicleLoggingFileMinutes; + public bool VehicleLoggingEnabled { get { return m_vehicleLoggingEnabled; } } public BSScene(string identifier) { @@ -197,19 +193,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters // can be left in and every call doesn't have to check for null. if (m_physicsLoggingEnabled) { - PhysicsLogging = new LogWriter(m_physicsLoggingDir, m_physicsLoggingPrefix, m_physicsLoggingFileMinutes); + PhysicsLogging = new Logging.LogWriter(m_physicsLoggingDir, m_physicsLoggingPrefix, m_physicsLoggingFileMinutes); } else { - PhysicsLogging = new LogWriter(); - } - if (m_vehicleLoggingEnabled) - { - VehicleLogging = new LogWriter(m_vehicleLoggingDir, m_vehicleLoggingPrefix, m_vehicleLoggingFileMinutes); - } - else - { - VehicleLogging = new LogWriter(); + PhysicsLogging = new Logging.LogWriter(); } // Get the version of the DLL @@ -218,11 +206,14 @@ public class BSScene : PhysicsScene, IPhysicsParameters // m_log.WarnFormat("{0}: BulletSim.dll version='{1}'", LogHeader, BulletSimVersion); // if Debug, enable logging from the unmanaged code - if (m_log.IsDebugEnabled) + if (m_log.IsDebugEnabled || PhysicsLogging.Enabled) { m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", LogHeader); - // the handle is saved to it doesn't get freed after this call - m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLogger); + if (PhysicsLogging.Enabled) + m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLoggerPhysLog); + else + m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLogger); + // the handle is saved in a variable to make sure it doesn't get freed after this call BulletSimAPI.SetDebugLogCallback(m_DebugLogCallbackHandle); } @@ -363,9 +354,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters m_physicsLoggingFileMinutes = pConfig.GetInt("PhysicsLoggingFileMinutes", 5); // Very detailed logging for vehicle debugging m_vehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false); - m_vehicleLoggingDir = pConfig.GetString("VehicleLoggingDir", "."); - m_vehicleLoggingPrefix = pConfig.GetString("VehicleLoggingPrefix", "vehicle-"); - m_vehicleLoggingFileMinutes = pConfig.GetInt("VehicleLoggingFileMinutes", 5); } } m_params[0] = parms; @@ -386,12 +374,17 @@ public class BSScene : PhysicsScene, IPhysicsParameters return ret; } - // Called directly from unmanaged code so don't do much private void BulletLogger(string msg) { m_log.Debug("[BULLETS UNMANAGED]:" + msg); } + + // Called directly from unmanaged code so don't do much + private void BulletLoggerPhysLog(string msg) + { + PhysicsLogging.Write("[BULLETS UNMANAGED]:" + msg); + } public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying) { @@ -532,7 +525,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters for (int ii = 0; ii < updatedEntityCount; ii++) { EntityProperties entprop = m_updateArray[ii]; - // m_log.DebugFormat("{0}: entprop[{1}]: id={2}, pos={3}", LogHeader, ii, entprop.ID, entprop.Position); BSPrim prim; if (m_prims.TryGetValue(entprop.ID, out prim)) { diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 086f0dc..babb707 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -146,6 +146,22 @@ public struct ConfigurationParameters public const float numericFalse = 0f; } +// Values used by Bullet and BulletSim to control collisions +public enum CollisionFlags : uint +{ + STATIC_OBJECT = 1 << 0, + KINEMATIC_OBJECT = 1 << 1, + NO_CONTACT_RESPONSE = 1 << 2, + CUSTOM_MATERIAL_CALLBACK = 1 << 3, + CHARACTER_OBJECT = 1 << 4, + DISABLE_VISUALIZE_OBJECT = 1 << 5, + DISABLE_SPU_COLLISION_PROCESS = 1 << 6, + // Following used by BulletSim to control collisions + VOLUME_DETECT_OBJECT = 1 << 10, + PHANTOM_OBJECT = 1 << 11, + PHYSICAL_OBJECT = 1 << 12, +}; + static class BulletSimAPI { [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] @@ -214,6 +230,9 @@ public static extern bool RemoveConstraint(uint worldID, uint id1, uint id2); public static extern Vector3 GetObjectPosition(uint WorldID, uint id); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern Quaternion GetObjectOrientation(uint WorldID, uint id); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern bool SetObjectTranslation(uint worldID, uint id, Vector3 position, Quaternion rotation); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] @@ -268,5 +287,37 @@ public static extern void DumpBulletStatistics(); public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern void SetDebugLogCallback(DebugLogCallback callback); + +// =============================================================================== +// =============================================================================== +// =============================================================================== +// A new version of the API that moves all the logic out of the C++ code and into +// the C# code. This will make modifications easier for the next person. +// This interface passes the actual pointers to the objects in the unmanaged +// address space. All the management (calls for creation/destruction/lookup) +// is done in the C# code. +// The names have a 2 tacked on. This will be removed as the code gets rebuilt +// and the old code is removed from the C# code. +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern IntPtr GetSimHandle2(uint worldID); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern IntPtr GetBodyHandleWorldID2(uint worldID, uint id); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern IntPtr GetBodyHandle2(IntPtr sim, uint id); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern IntPtr ClearForces2(IntPtr obj); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern IntPtr SetCollisionFlags2(IntPtr obj, uint flags); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern IntPtr AddToCollisionFlags2(IntPtr obj, uint flags); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern IntPtr RemoveFromCollisionFlags2(IntPtr obj, uint flags); + } } -- cgit v1.1 From b25d874afaa5a3111455b9e49a73343b3afd6f14 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 20 Jul 2012 15:34:19 -0700 Subject: BulletSim: add reference to OpenSim.Region.CoreModules in BSScene.cs attempting to fix a mono compile error. --- .../CoreModules/Framework/Statistics/Logging/BinaryLoggingModule.cs | 2 +- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/Framework/Statistics/Logging/BinaryLoggingModule.cs b/OpenSim/Region/CoreModules/Framework/Statistics/Logging/BinaryLoggingModule.cs index 9b1b1a3..fb74cc6 100644 --- a/OpenSim/Region/CoreModules/Framework/Statistics/Logging/BinaryLoggingModule.cs +++ b/OpenSim/Region/CoreModules/Framework/Statistics/Logging/BinaryLoggingModule.cs @@ -39,7 +39,7 @@ using OpenSim.Region.Framework; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; -namespace OpenSim.Region.CoreModules.Statistics.Logging +namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging { [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "BinaryLoggingModule")] public class BinaryLoggingModule : INonSharedRegionModule diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 9d41ce8..8773485 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -31,8 +31,9 @@ using System.Text; using System.Threading; using OpenSim.Framework; using OpenSim.Region.Framework; -using OpenSim.Region.Physics.Manager; +using OpenSim.Region.CoreModules; using Logging = OpenSim.Region.CoreModules.Framework.Statistics.Logging; +using OpenSim.Region.Physics.Manager; using Nini.Config; using log4net; using OpenMetaverse; -- cgit v1.1 From 7d16d0664e7d5395bcafac1ece6a87fe231ea598 Mon Sep 17 00:00:00 2001 From: Melanie Date: Mon, 23 Jul 2012 19:21:59 +0100 Subject: Commiting Avination's memleak fix-a-thon, installment #1 As the MinHeap shrinks, free object references that have been sent. Also, free the last item when it empties. --- OpenSim/Framework/MinHeap.cs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Framework/MinHeap.cs b/OpenSim/Framework/MinHeap.cs index 33d0364..99ac25d 100644 --- a/OpenSim/Framework/MinHeap.cs +++ b/OpenSim/Framework/MinHeap.cs @@ -63,12 +63,15 @@ namespace OpenSim.Framework internal void Clear() { - this.value = default(T); if (this.handle != null) - { this.handle.Clear(); - this.handle = null; - } + ClearRef(); + } + + internal void ClearRef() + { + this.value = default(T); + this.handle = null; } } @@ -285,6 +288,7 @@ namespace OpenSim.Framework if (--this.size > 0 && index != this.size) { Set(this.items[this.size], index); + this.items[this.size].ClearRef(); if (!BubbleUp(index)) BubbleDown(index); } -- cgit v1.1 From 55c1c10c0dc3f189107ab43b43988a8b8833f136 Mon Sep 17 00:00:00 2001 From: Melanie Date: Mon, 23 Jul 2012 19:26:21 +0100 Subject: Committing Avination's memleak fix-a-thon, installment #2 Ensure items coming off the lockless queue are released. Also ensure this is done when the queue is cleared. --- OpenSim/Framework/LocklessQueue.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'OpenSim') diff --git a/OpenSim/Framework/LocklessQueue.cs b/OpenSim/Framework/LocklessQueue.cs index dd3d201..84f887c 100644 --- a/OpenSim/Framework/LocklessQueue.cs +++ b/OpenSim/Framework/LocklessQueue.cs @@ -99,8 +99,13 @@ namespace OpenSim.Framework } else { - item = oldHeadNext.Item; + item = oldHeadNext.Item; haveAdvancedHead = CAS(ref head, oldHead, oldHeadNext); + if (haveAdvancedHead) + { + oldHeadNext.Item = default(T); + oldHead.Next = null; + } } } } @@ -111,6 +116,10 @@ namespace OpenSim.Framework public void Clear() { + // ugly + T item; + while(count > 0) + Dequeue(out item); Init(); } -- cgit v1.1 From fc77bca936e7d28b4e92a73289124b41cd50b553 Mon Sep 17 00:00:00 2001 From: Melanie Date: Mon, 23 Jul 2012 19:53:26 +0100 Subject: Committing Avination's memleak fix-a-thon, installment #3 When linking, detach the no longer used SOG's from backup so they can be collected. Since their Children collection is never emptied, they prevent their former SOPs from being collected as well. --- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'OpenSim') diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index ba68dfa..13842ad 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -1638,6 +1638,8 @@ namespace OpenSim.Region.Framework.Scenes { parentGroup.LinkToGroup(child); + child.DetachFromBackup(); + // this is here so physics gets updated! // Don't remove! Bad juju! Stay away! or fix physics! child.AbsolutePosition = child.AbsolutePosition; -- cgit v1.1 From e126915bc168f16f2c4462492814a1b733aefe87 Mon Sep 17 00:00:00 2001 From: Melanie Date: Mon, 23 Jul 2012 21:08:02 +0200 Subject: Change attachment handling to remove object from the scene first as per justincc's original work. Sample scripts before doing so. Also refactor some crucial common code and eliminate parameters that were only ever used with the same constant value. --- .../Avatar/Attachments/AttachmentsModule.cs | 88 +++++++++++++++------- .../Framework/Interfaces/IAttachmentsModule.cs | 2 +- .../Region/Framework/Interfaces/IScenePresence.cs | 4 +- OpenSim/Region/Framework/Scenes/Scene.cs | 12 +-- .../Scenes/Serialization/SceneObjectSerializer.cs | 18 +++++ 5 files changed, 82 insertions(+), 42 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index 0f3b1e8..464dfd3 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -28,6 +28,8 @@ using System; using System.Collections.Generic; using System.Reflection; +using System.IO; +using System.Xml; using log4net; using Mono.Addins; using Nini.Config; @@ -202,7 +204,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments } } - public void DeRezAttachments(IScenePresence sp, bool saveChanged, bool saveAllScripted) + public void DeRezAttachments(IScenePresence sp) { if (!Enabled) return; @@ -213,18 +215,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments { foreach (SceneObjectGroup so in sp.GetAttachments()) { - // We can only remove the script instances from the script engine after we've retrieved their xml state - // when we update the attachment item. - m_scene.DeleteSceneObject(so, false, false); - - if (saveChanged || saveAllScripted) - { - so.IsAttachment = false; - so.AbsolutePosition = so.RootPart.AttachedPos; - UpdateKnownItem(sp, so, saveAllScripted); - } - - so.RemoveScriptInstances(true); + UpdateDetachedObject(sp, so); } sp.ClearAttachments(); @@ -528,7 +519,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments /// /// /// - private void UpdateKnownItem(IScenePresence sp, SceneObjectGroup grp, bool saveAllScripted) + private void UpdateKnownItem(IScenePresence sp, SceneObjectGroup grp, string scriptedState) { // Saving attachments for NPCs messes them up for the real owner! INPCModule module = m_scene.RequestModuleInterface(); @@ -538,13 +529,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments return; } - if (grp.HasGroupChanged || (saveAllScripted && grp.ContainsScripts())) + if (grp.HasGroupChanged) { // m_log.DebugFormat( // "[ATTACHMENTS MODULE]: Updating asset for attachment {0}, attachpoint {1}", // grp.UUID, grp.AttachmentPoint); - string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp); + string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp, scriptedState); InventoryItemBase item = new InventoryItemBase(grp.FromItemID, sp.UUID); item = m_scene.InventoryService.GetItem(item); @@ -683,29 +674,68 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments return newItem; } - private void DetachSingleAttachmentToInvInternal(IScenePresence sp, SceneObjectGroup so) + private string GetObjectScriptStates(SceneObjectGroup grp) { - // m_log.DebugFormat("[ATTACHMENTS MODULE]: Detaching item {0} to inventory for {1}", itemID, sp.Name); + using (StringWriter sw = new StringWriter()) + { + using (XmlTextWriter writer = new XmlTextWriter(sw)) + { + grp.SaveScriptedState(writer); + } - m_scene.EventManager.TriggerOnAttach(so.LocalId, so.FromItemID, UUID.Zero); - sp.RemoveAttachment(so); + return sw.ToString(); + } + } + + private void UpdateDetachedObject(IScenePresence sp, SceneObjectGroup so) + { + // Don't save attachments for HG visitors, it + // messes up their inventory. When a HG visitor logs + // out on a foreign grid, their attachments will be + // reloaded in the state they were in when they left + // the home grid. This is best anyway as the visited + // grid may use an incompatible script engine. + bool saveChanged + = sp.PresenceType != PresenceType.Npc + && (m_scene.UserManagementModule == null + || m_scene.UserManagementModule.IsLocalGridUser(sp.UUID)); + + // Scripts MUST be snapshotted before the object is + // removed from the scene because doing otherwise will + // clobber the run flag + string scriptedState = GetObjectScriptStates(so); + + // Remove the object from the scene so no more updates + // are sent. Doing this before the below changes will ensure + // updates can't cause "HUD artefacts" + m_scene.DeleteSceneObject(so, false, false); // Prepare sog for storage so.AttachedAvatar = UUID.Zero; so.RootPart.SetParentLocalId(0); so.IsAttachment = false; - // We cannot use AbsolutePosition here because that would - // attempt to cross the prim as it is detached - so.ForEachPart(x => { x.GroupPosition = so.RootPart.AttachedPos; }); + if (saveChanged) + { + // We cannot use AbsolutePosition here because that would + // attempt to cross the prim as it is detached + so.ForEachPart(x => { x.GroupPosition = so.RootPart.AttachedPos; }); + + UpdateKnownItem(sp, so, scriptedState); + } + + // Now, remove the scripts + so.RemoveScriptInstances(true); + } - UpdateKnownItem(sp, so, true); + private void DetachSingleAttachmentToInvInternal(IScenePresence sp, SceneObjectGroup so) + { + // m_log.DebugFormat("[ATTACHMENTS MODULE]: Detaching item {0} to inventory for {1}", itemID, sp.Name); + + m_scene.EventManager.TriggerOnAttach(so.LocalId, so.FromItemID, UUID.Zero); + sp.RemoveAttachment(so); - // This MUST happen AFTER serialization because it will - // either stop or remove the scripts. Both will cause scripts - // to be serialized in a stopped state with the true run - // state already lost. - m_scene.DeleteSceneObject(so, false, true); + UpdateDetachedObject(sp, so); } private SceneObjectGroup RezSingleAttachmentFromInventoryInternal( diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs index 351e603..d5200b7 100644 --- a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs @@ -65,7 +65,7 @@ namespace OpenSim.Region.Framework.Interfaces /// The presence closing /// Save changed attachments. /// Save attachments with scripts even if they haven't changed. - void DeRezAttachments(IScenePresence sp, bool saveChanged, bool saveAllScripted); + void DeRezAttachments(IScenePresence sp); /// /// Delete all the presence's attachments from the scene diff --git a/OpenSim/Region/Framework/Interfaces/IScenePresence.cs b/OpenSim/Region/Framework/Interfaces/IScenePresence.cs index e6b926c..3f68ee0 100644 --- a/OpenSim/Region/Framework/Interfaces/IScenePresence.cs +++ b/OpenSim/Region/Framework/Interfaces/IScenePresence.cs @@ -40,6 +40,8 @@ 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. @@ -83,4 +85,4 @@ namespace OpenSim.Region.Framework.Interfaces void RemoveAttachment(SceneObjectGroup gobj); void ClearAttachments(); } -} \ No newline at end of file +} diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 51a6820..ee34338 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -3297,17 +3297,7 @@ namespace OpenSim.Region.Framework.Scenes { if (AttachmentsModule != null) { - // Don't save attachments for HG visitors, it - // messes up their inventory. When a HG visitor logs - // out on a foreign grid, their attachments will be - // reloaded in the state they were in when they left - // the home grid. This is best anyway as the visited - // grid may use an incompatible script engine. - bool saveChanged - = avatar.PresenceType != PresenceType.Npc - && (UserManagementModule == null || UserManagementModule.IsLocalGridUser(avatar.UUID)); - - AttachmentsModule.DeRezAttachments(avatar, saveChanged, false); + AttachmentsModule.DeRezAttachments(avatar); } ForEachClient( diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs index 0b34156..2d4c60a 100644 --- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs +++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs @@ -151,6 +151,24 @@ namespace OpenSim.Region.Framework.Scenes.Serialization ToOriginalXmlFormat(sceneObject, writer, doScriptStates, false); } + public static string ToOriginalXmlFormat(SceneObjectGroup sceneObject, string scriptedState) + { + using (StringWriter sw = new StringWriter()) + { + using (XmlTextWriter writer = new XmlTextWriter(sw)) + { + writer.WriteStartElement(String.Empty, "SceneObjectGroup", String.Empty); + + ToOriginalXmlFormat(sceneObject, writer, false, true); + + writer.WriteRaw(scriptedState); + + writer.WriteEndElement(); + } + return sw.ToString(); + } + } + /// /// Serialize a scene object to the original xml format /// -- cgit v1.1 From 73f9e14b4326042dd218abd11f72eb46339c3a29 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Mon, 23 Jul 2012 09:30:28 -0700 Subject: BulletSim: improve linking to add each link individually rather than rebuilding the object each time. Makes it an O(n) operation rather than O(n\!). --- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 136 ++++++++++++++----------- 1 file changed, 76 insertions(+), 60 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 71a4303..a749a97 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -149,22 +149,26 @@ public sealed class BSPrim : PhysicsActor { // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID); // DetailLog("{0},Destroy", LocalID); + // Undo any vehicle properties _vehicle.ProcessTypeChange(Vehicle.TYPE_NONE); _scene.RemoveVehiclePrim(this); // just to make sure - // 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; - } - _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 possible children depending on me + UnlinkAllChildren(); + // everything in the C# world will get garbage collected. Tell the C++ world to free stuff. - BulletSimAPI.DestroyObject(_scene.WorldID, _localID); + BulletSimAPI.DestroyObject(_scene.WorldID, LocalID); }); } @@ -272,7 +276,8 @@ public sealed class BSPrim : PhysicsActor 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 + // RecreateGeomAndObject(); // rebuild my shape with the new child added + LinkAChildToMe(pchild); // build the physical binding between me and the child } }); return; @@ -289,13 +294,18 @@ public sealed class BSPrim : PhysicsActor { DebugLog("{0}: RemoveChildFromLinkset: Removing constraint to {1}", LogHeader, child.LocalID); DetailLog("{0},RemoveChildToLinkset,child={1}", LocalID, pchild.LocalID); - if (!BulletSimAPI.RemoveConstraintByID(_scene.WorldID, child.LocalID)) - { - m_log.ErrorFormat("{0}: RemoveChildFromLinkset: Failed remove constraint for {1}", LogHeader, child.LocalID); - } _childrenPrims.Remove(child); child._parentPrim = null; // the child has lost its parent - RecreateGeomAndObject(); // rebuild my shape with the child removed + 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); + } } else { @@ -1247,30 +1257,6 @@ public sealed class BSPrim : PhysicsActor } } - // Create a linkset by creating a compound hull at the root prim that consists of all - // the children. - // NOTE: This does not allow proper collisions with the children prims so it is not a workable solution - void CreateLinksetWithCompoundHull() - { - // If I am the root prim of a linkset, replace my physical shape with all the - // pieces of the children. - // All of the children should have called CreateGeom so they have a hull - // in the physics engine already. Here we pull together all of those hulls - // into one shape. - int totalPrimsInLinkset = _childrenPrims.Count + 1; - // m_log.DebugFormat("{0}: CreateLinkset. Root prim={1}, prims={2}", LogHeader, LocalID, totalPrimsInLinkset); - ShapeData[] shapes = new ShapeData[totalPrimsInLinkset]; - FillShapeInfo(out shapes[0]); - int ii = 1; - foreach (BSPrim prim in _childrenPrims) - { - // m_log.DebugFormat("{0}: CreateLinkset: adding prim {1}", LogHeader, prim.LocalID); - prim.FillShapeInfo(out shapes[ii]); - ii++; - } - BulletSimAPI.CreateLinkset(_scene.WorldID, totalPrimsInLinkset, shapes); - } - // Copy prim's info into the BulletSim shape description structure public void FillShapeInfo(out ShapeData shape) { @@ -1290,9 +1276,10 @@ 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. - // TODO: make this more effeicient: a large linkset gets rebuilt over and over and prims are added void CreateLinksetWithConstraints() { DebugLog("{0}: CreateLinkset. Root prim={1}, prims={2}", LogHeader, LocalID, _childrenPrims.Count+1); @@ -1306,29 +1293,58 @@ public sealed class BSPrim : PhysicsActor // create constraints between the root prim and each of the children foreach (BSPrim prim in _childrenPrims) { - // Zero motion for children so they don't interpolate - prim.ZeroMotion(); - - // relative position normalized to the root prim - OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(this._orientation); - OMV.Vector3 childRelativePosition = (prim._position - this._position) * invThisOrientation; - - // relative rotation of the child to the parent - OMV.Quaternion childRelativeRotation = invThisOrientation * prim._orientation; - - // this is 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, prim.LocalID); - BulletSimAPI.AddConstraint(_scene.WorldID, LocalID, prim.LocalID, - childRelativePosition, - childRelativeRotation, - OMV.Vector3.Zero, - OMV.Quaternion.Identity, - OMV.Vector3.Zero, OMV.Vector3.Zero, - OMV.Vector3.Zero, OMV.Vector3.Zero); + 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); + 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); + } + + // 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); + } + + // 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); + 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. // No locking here because this is done when the physics engine is not simulating -- cgit v1.1 From 85c6eb7c500b708ab0a91965eca9da20b0b02e50 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Mon, 23 Jul 2012 10:37:52 -0700 Subject: BulletSim: add all the new functions to BulletSimAPI. Modify ZeroMotion() to not make tainting calls and to use new API calls. --- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 13 +- .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 132 ++++++++++++++++++++- 2 files changed, 139 insertions(+), 6 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index a749a97..29ddddd 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -324,11 +324,20 @@ public sealed class BSPrim : PhysicsActor // 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() { - Velocity = OMV.Vector3.Zero; + _velocity = OMV.Vector3.Zero; _acceleration = OMV.Vector3.Zero; - RotationalVelocity = OMV.Vector3.Zero; + _rotationalVelocity = OMV.Vector3.Zero; + + 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); + + // make sure this new information is pushed to the client base.RequestPhysicsterseUpdate(); } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index babb707..54a8cfd 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -291,13 +291,14 @@ public static extern void SetDebugLogCallback(DebugLogCallback callback); // =============================================================================== // =============================================================================== // =============================================================================== -// A new version of the API that moves all the logic out of the C++ code and into +// A new version of the API that enables moving all the logic out of the C++ code and into // the C# code. This will make modifications easier for the next person. // This interface passes the actual pointers to the objects in the unmanaged // address space. All the management (calls for creation/destruction/lookup) // is done in the C# code. -// The names have a 2 tacked on. This will be removed as the code gets rebuilt -// and the old code is removed from the C# code. +// The names have a "2" tacked on. This will be removed as the C# code gets rebuilt +// and the old code is removed. + [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern IntPtr GetSimHandle2(uint worldID); @@ -307,8 +308,101 @@ public static extern IntPtr GetBodyHandleWorldID2(uint worldID, uint id); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern IntPtr GetBodyHandle2(IntPtr sim, uint id); +// =============================================================================== [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr ClearForces2(IntPtr obj); +public static extern IntPtr Initialize2(Vector3 maxPosition, IntPtr parms, + int maxCollisions, IntPtr collisionArray, + int maxUpdates, IntPtr updateArray); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool UpdateParameter2(IntPtr sim, uint localID, String parm, float value); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void SetHeightmap2(IntPtr sim, float[] heightmap); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void Shutdown2(IntPtr sim); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern int PhysicsStep2(IntPtr sim, float timeStep, int maxSubSteps, float fixedTimeStep, + out int updatedEntityCount, + out IntPtr updatedEntitiesPtr, + out int collidersCount, + out IntPtr collidersPtr); + +/* +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern IntPtr CreateMesh2(IntPtr sim, int indicesCount, int* indices, int verticesCount, float* vertices ); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool BuildHull2(IntPtr sim, IntPtr mesh); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool ReleaseHull2(IntPtr sim, IntPtr mesh); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool DestroyMesh2(IntPtr sim, IntPtr mesh); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +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); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool DestroyConstraint2(IntPtr sim, IntPtr constrain); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern Vector3 GetPosition2(IntPtr obj); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern Quaternion GetOrientation2(IntPtr obj); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool SetTranslation2(IntPtr obj, Vector3 position, Quaternion rotation); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool SetVelocity2(IntPtr obj, Vector3 velocity); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool SetAngularVelocity2(IntPtr obj, Vector3 angularVelocity); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool SetObjectForce2(IntPtr obj, Vector3 force); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool SetCcdMotionThreshold2(IntPtr obj, float val); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool SetCcdSweepSphereRadius2(IntPtr obj, float val); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool SetDamping2(IntPtr obj, float lin_damping, float ang_damping); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool SetDeactivationTime2(IntPtr obj, float val); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool SetSleepingThresholds2(IntPtr obj, float lin_threshold, float ang_threshold); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool SetContactProcessingThreshold2(IntPtr obj, float val); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool SetFriction2(IntPtr obj, float val); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool SetRestitution2(IntPtr obj, float val); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool SetLinearVelocity2(IntPtr obj, Vector3 val); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool SetInterpolation2(IntPtr obj, Vector3 lin, Vector3 ang); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern IntPtr SetCollisionFlags2(IntPtr obj, uint flags); @@ -319,5 +413,35 @@ public static extern IntPtr AddToCollisionFlags2(IntPtr obj, uint flags); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern IntPtr RemoveFromCollisionFlags2(IntPtr obj, uint flags); +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool SetMassProps2(IntPtr obj, float mass, Vector3 inertia); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool UpdateInertiaTensor2(IntPtr obj); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool SetGravity2(IntPtr obj, Vector3 val); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern IntPtr ClearForces2(IntPtr obj); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool SetMargin2(IntPtr obj, float val); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool UpdateSingleAabb2(IntPtr world, IntPtr obj); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool AddObjectToWorld2(IntPtr world, IntPtr obj); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool RemoveObjectFromWorld2(IntPtr world, IntPtr obj); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool DestroyObject2(IntPtr world, uint id); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void DumpPhysicsStatistics2(IntPtr sim); + } } -- cgit v1.1 From 8a574395c7626f0aef596cbb928e0b4139ebab12 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Mon, 23 Jul 2012 13:48:40 -0700 Subject: BulletSim: add Dispose() code to free up resources and close log files. --- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'OpenSim') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 8773485..7cc3fe3 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -630,6 +630,27 @@ public class BSScene : PhysicsScene, IPhysicsParameters public override void Dispose() { // m_log.DebugFormat("{0}: Dispose()", LogHeader); + + // make sure no stepping happens while we're deleting stuff + m_initialized = false; + + foreach (KeyValuePair kvp in m_avatars) + { + kvp.Value.Destroy(); + } + m_avatars.Clear(); + + foreach (KeyValuePair kvp in m_prims) + { + kvp.Value.Destroy(); + } + m_prims.Clear(); + + // Anything left in the unmanaged code should be cleaned out + BulletSimAPI.Shutdown(WorldID); + + // Not logging any more + PhysicsLogging.Close(); } public override Dictionary GetTopColliders() -- cgit v1.1 From dda681515b31e528ae01954a583cd7a7b4e94987 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Mon, 23 Jul 2012 13:49:31 -0700 Subject: BulletSim: small optimizations for link and unlink code --- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 29ddddd..b49b8d9 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -293,7 +293,7 @@ public sealed class BSPrim : PhysicsActor if (_childrenPrims.Contains(child)) { DebugLog("{0}: RemoveChildFromLinkset: Removing constraint to {1}", LogHeader, child.LocalID); - DetailLog("{0},RemoveChildToLinkset,child={1}", LocalID, pchild.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) @@ -331,14 +331,12 @@ public sealed class BSPrim : PhysicsActor _acceleration = OMV.Vector3.Zero; _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); - - // make sure this new information is pushed to the client - base.RequestPhysicsterseUpdate(); } public override void LockAngularMotion(OMV.Vector3 axis) @@ -1253,7 +1251,7 @@ public sealed class BSPrim : PhysicsActor if (IsRootOfLinkset) { // Create a linkset around this object - CreateLinksetWithConstraints(); + CreateLinkset(); } else { @@ -1289,16 +1287,14 @@ public sealed class BSPrim : PhysicsActor // Create the linkset by putting constraints between the objects of the set so they cannot move // relative to each other. - void CreateLinksetWithConstraints() + void CreateLinkset() { DebugLog("{0}: CreateLinkset. Root prim={1}, prims={2}", LogHeader, LocalID, _childrenPrims.Count+1); // remove any constraints that might be in place - foreach (BSPrim prim in _childrenPrims) - { - DebugLog("{0}: CreateLinkset: RemoveConstraint between root prim {1} and child prim {2}", LogHeader, LocalID, prim.LocalID); - BulletSimAPI.RemoveConstraint(_scene.WorldID, LocalID, prim.LocalID); - } + DebugLog("{0}: CreateLinkset: RemoveConstraints between me and any children", LogHeader, LocalID); + BulletSimAPI.RemoveConstraintByID(_scene.WorldID, LocalID); + // create constraints between the root prim and each of the children foreach (BSPrim prim in _childrenPrims) { @@ -1430,7 +1426,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 (this._parentPrim == null) + if (_parentPrim == null) { // Assign to the local variables so the normal set action does not happen _position = entprop.Position; -- cgit v1.1 From bf6547be01afbd7f79eea19013cfd068ad87837f Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Mon, 23 Jul 2012 16:31:12 -0700 Subject: BulletSim: change how prim mass is saved so it is always calculated but zero is given if not physical. --- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 43 ++++++++++++++------------ 1 file changed, 23 insertions(+), 20 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index b49b8d9..a19d6d7 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -133,10 +133,7 @@ public sealed class BSPrim : PhysicsActor _parentPrim = null; // not a child or a parent _vehicle = new BSDynamics(this); // add vehicleness _childrenPrims = new List(); - if (_isPhysical) - _mass = CalculateMass(); - else - _mass = 0f; + _mass = CalculateMass(); // do the actual object creation at taint time _scene.TaintedObject(delegate() { @@ -181,8 +178,8 @@ public sealed class BSPrim : PhysicsActor _size = value; _scene.TaintedObject(delegate() { - if (_isPhysical) _mass = CalculateMass(); // changing size changes the mass - BulletSimAPI.SetObjectScaleMass(_scene.WorldID, _localID, _scale, _mass, _isPhysical); + _mass = CalculateMass(); // changing size changes the mass + BulletSimAPI.SetObjectScaleMass(_scene.WorldID, _localID, _scale, Mass, IsPhysical); RecreateGeomAndObject(); }); } @@ -192,7 +189,7 @@ public sealed class BSPrim : PhysicsActor _pbs = value; _scene.TaintedObject(delegate() { - if (_isPhysical) _mass = CalculateMass(); // changing the shape changes the mass + _mass = CalculateMass(); // changing the shape changes the mass RecreateGeomAndObject(); }); } @@ -278,6 +275,8 @@ public sealed class BSPrim : PhysicsActor 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; @@ -306,6 +305,8 @@ public sealed class BSPrim : PhysicsActor // RecreateGeomAndObject(); // rebuild my shape with the child removed UnlinkAChildFromMe(pchild); } + + _mass = CalculateMass(); } else { @@ -364,9 +365,17 @@ public sealed class BSPrim : PhysicsActor }); } } + + // Return the effective mass of the object. Non-physical objects do not have mass. public override float Mass { - get { return _mass; } + get { + if (IsPhysical) + return _mass; + else + return 0f; + } } + public override OMV.Vector3 Force { get { return _force; } set { @@ -446,7 +455,8 @@ public sealed class BSPrim : PhysicsActor // Called from Scene when doing simulation step so we're in taint processing time. public void StepVehicle(float timeStep) { - _vehicle.Step(timeStep); + if (IsPhysical) + _vehicle.Step(timeStep); } // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more @@ -543,20 +553,13 @@ public sealed class BSPrim : PhysicsActor { // 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 = 0f; - } - else + if (!IsStatic) { _mass = CalculateMass(); - // If it's dynamic, make sure the hull has been created for it - // This shouldn't do much work if the object had previously been built RecreateGeomAndObject(); - } - DetailLog("{0},SetObjectDynamic,taint,static={1},solid={2},mass={3}", LocalID, IsStatic, IsSolid, _mass); - BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), _mass); + 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 @@ -1273,7 +1276,7 @@ public sealed class BSPrim : PhysicsActor shape.Rotation = _orientation; shape.Velocity = _velocity; shape.Scale = _scale; - shape.Mass = _isPhysical ? _mass : 0f; + shape.Mass = Mass; shape.Buoyancy = _buoyancy; shape.HullKey = _hullKey; shape.MeshKey = _meshKey; -- cgit v1.1 From 2858b1b1f44f67d7ac88b5dcaffbc9710e9e365c Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 24 Jul 2012 22:33:54 +0100 Subject: extend regression TestDetachScriptedAttachementToInventory() to check correct running status on a re-rezzed attachment --- .../Attachments/Tests/AttachmentsModuleTests.cs | 28 +++++++++++++++++++--- .../Tests/Common/Helpers/TaskInventoryHelpers.cs | 22 +++++++++++++++-- 2 files changed, 45 insertions(+), 5 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs index b021a47..8d2128c 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs @@ -47,6 +47,8 @@ using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; using OpenSim.Region.CoreModules.World.Serialiser; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.ScriptEngine.Interfaces; +using OpenSim.Region.ScriptEngine.Shared.Instance; using OpenSim.Region.ScriptEngine.XEngine; using OpenSim.Services.Interfaces; using OpenSim.Tests.Common; @@ -379,29 +381,49 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1); SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, sp.UUID, "att-name", 0x10); - TaskInventoryHelpers.AddScript(scene, so.RootPart); + TaskInventoryItem scriptTaskItem + = TaskInventoryHelpers.AddScript( + scene, + so.RootPart, + "scriptItem", + "default { attach(key id) { if (id != NULL_KEY) { llSay(0, \"Hello World\"); } } }"); + InventoryItemBase userItem = UserInventoryHelpers.AddInventoryItem(scene, so, 0x100, 0x1000); // FIXME: Right now, we have to do a tricksy chat listen to make sure we know when the script is running. // In the future, we need to be able to do this programatically more predicably. scene.EventManager.OnChatFromWorld += OnChatFromWorld; - SceneObjectGroup soRezzed + SceneObjectGroup rezzedSo = scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest); // Wait for chat to signal rezzed script has been started. m_chatEvent.WaitOne(60000); - scene.AttachmentsModule.DetachSingleAttachmentToInv(sp, soRezzed); + scene.AttachmentsModule.DetachSingleAttachmentToInv(sp, rezzedSo); InventoryItemBase userItemUpdated = scene.InventoryService.GetItem(userItem); AssetBase asset = scene.AssetService.Get(userItemUpdated.AssetID.ToString()); + // TODO: It would probably be better here to check script state via the saving and retrieval of state + // information at a higher level, rather than having to inspect the serialization. XmlDocument soXml = new XmlDocument(); soXml.LoadXml(Encoding.UTF8.GetString(asset.Data)); XmlNodeList scriptStateNodes = soXml.GetElementsByTagName("ScriptState"); Assert.That(scriptStateNodes.Count, Is.EqualTo(1)); + + // Re-rez the attachment to check script running state + SceneObjectGroup reRezzedSo = scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest); + + // Wait for chat to signal rezzed script has been started. + m_chatEvent.WaitOne(60000); + + TaskInventoryItem reRezzedScriptItem = reRezzedSo.RootPart.Inventory.GetInventoryItem(scriptTaskItem.Name); + IScriptModule xengine = scene.RequestModuleInterface(); + Assert.That(xengine.GetScriptState(reRezzedScriptItem.ItemID), Is.True); + +// Console.WriteLine(soXml.OuterXml); } /// diff --git a/OpenSim/Tests/Common/Helpers/TaskInventoryHelpers.cs b/OpenSim/Tests/Common/Helpers/TaskInventoryHelpers.cs index fba03ab..0a2b30a 100644 --- a/OpenSim/Tests/Common/Helpers/TaskInventoryHelpers.cs +++ b/OpenSim/Tests/Common/Helpers/TaskInventoryHelpers.cs @@ -80,8 +80,26 @@ namespace OpenSim.Tests.Common /// The item that was added public static TaskInventoryItem AddScript(Scene scene, SceneObjectPart part) { + return AddScript(scene, part, "scriptItem", "default { state_entry() { llSay(0, \"Hello World\"); } }"); + } + + /// + /// Add a simple script to the given part. + /// + /// + /// TODO: Accept input for item and asset IDs to avoid mysterious script failures that try to use any of these + /// functions more than once in a test. + /// + /// + /// + /// Name of the script to add + /// LSL script source + /// The item that was added + public static TaskInventoryItem AddScript( + Scene scene, SceneObjectPart part, string scriptName, string scriptSource) + { AssetScriptText ast = new AssetScriptText(); - ast.Source = "default { state_entry() { llSay(0, \"Hello World\"); } }"; + ast.Source = scriptSource; ast.Encode(); UUID assetUuid = new UUID("00000000-0000-0000-1000-000000000000"); @@ -91,7 +109,7 @@ namespace OpenSim.Tests.Common scene.AssetService.Store(asset); TaskInventoryItem item = new TaskInventoryItem - { Name = "scriptItem", AssetID = assetUuid, ItemID = itemUuid, + { Name = scriptName, AssetID = assetUuid, ItemID = itemUuid, Type = (int)AssetType.LSLText, InvType = (int)InventoryType.LSL }; part.Inventory.AddInventoryItem(item, true); -- cgit v1.1 From c99262957630749debbf12372cab88c1f3faa6b8 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 24 Jul 2012 22:40:06 +0100 Subject: extend regression TestRezScriptedAttachmentFromInventory() to check actual start of script rather than just the script status reported by SOG.ContainsScripts() --- .../Attachments/Tests/AttachmentsModuleTests.cs | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs index 8d2128c..8337345 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs @@ -291,21 +291,37 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests { TestHelpers.InMethod(); - Scene scene = CreateTestScene(); + Scene scene = CreateScriptingEnabledTestScene(); UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); - ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1.PrincipalID); + ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1); SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, sp.UUID, "att-name", 0x10); - TaskInventoryHelpers.AddScript(scene, so.RootPart); + TaskInventoryItem scriptItem + = TaskInventoryHelpers.AddScript( + scene, + so.RootPart, + "scriptItem", + "default { attach(key id) { if (id != NULL_KEY) { llSay(0, \"Hello World\"); } } }"); + InventoryItemBase userItem = UserInventoryHelpers.AddInventoryItem(scene, so, 0x100, 0x1000); + // FIXME: Right now, we have to do a tricksy chat listen to make sure we know when the script is running. + // In the future, we need to be able to do this programatically more predicably. + scene.EventManager.OnChatFromWorld += OnChatFromWorld; + scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest); + m_chatEvent.WaitOne(60000); + // TODO: Need to have a test that checks the script is actually started but this involves a lot more // plumbing of the script engine and either pausing for events or more infrastructure to turn off various // script engine delays/asychronicity that isn't helpful in an automated regression testing context. SceneObjectGroup attSo = scene.GetSceneObjectGroup(so.Name); Assert.That(attSo.ContainsScripts(), Is.True); + + TaskInventoryItem reRezzedScriptItem = attSo.RootPart.Inventory.GetInventoryItem(scriptItem.Name); + IScriptModule xengine = scene.RequestModuleInterface(); + Assert.That(xengine.GetScriptState(reRezzedScriptItem.ItemID), Is.True); } [Test] -- cgit v1.1 From c846a5461ca2f27a1ddb4a6cad12194e8eb3b955 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 24 Jul 2012 22:46:22 +0100 Subject: Remove bad using statement in AttachmentsModuleTests. It seems that the mono 2.10.8.1 doesn't choke on this but for some reason 2.4.3 fails. --- .../CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs index 8337345..6e7a414 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs @@ -48,7 +48,6 @@ using OpenSim.Region.CoreModules.World.Serialiser; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.ScriptEngine.Interfaces; -using OpenSim.Region.ScriptEngine.Shared.Instance; using OpenSim.Region.ScriptEngine.XEngine; using OpenSim.Services.Interfaces; using OpenSim.Tests.Common; @@ -307,7 +306,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests // FIXME: Right now, we have to do a tricksy chat listen to make sure we know when the script is running. // In the future, we need to be able to do this programatically more predicably. - scene.EventManager.OnChatFromWorld += OnChatFromWorld; + scene.EventManager.OnChatFromWorld += OnChatFromWorld; scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest); -- cgit v1.1 From ef8570f78918510f2f92fce7cffdb49674bad928 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 24 Jul 2012 23:39:31 +0100 Subject: Extend region console "show queues" command to show already collected time since last packeted received by the simulator from a viewer. --- .../Region/ClientStack/Linden/UDP/LLUDPClient.cs | 3 +- .../Agent/UDP/Linden/LindenUDPInfoModule.cs | 42 ++++++++++++---------- 2 files changed, 26 insertions(+), 19 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs index ffa3be4..8963756 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs @@ -278,7 +278,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP public string GetStats() { return string.Format( - "{0,7} {1,7} {2,7} {3,9} {4,7} {5,7} {6,7} {7,7} {8,7} {9,8} {10,7} {11,7}", + "{0,7} {1,7} {2,7} {3,9} {4,7} {5,7} {6,7} {7,7} {8,7} {9,8} {10,7} {11,7} {12,7}", + Util.EnvironmentTickCountSubtract(TickLastPacketReceived), PacketsReceived, PacketsSent, PacketsResent, diff --git a/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs b/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs index a7ebecc..906c1d4 100644 --- a/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs +++ b/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs @@ -373,17 +373,22 @@ namespace OpenSim.Region.CoreModules.UDP.Linden int maxNameLength = 18; int maxRegionNameLength = 14; int maxTypeLength = 4; - int totalInfoFieldsLength = maxNameLength + columnPadding + maxRegionNameLength + columnPadding + maxTypeLength + columnPadding; + + int totalInfoFieldsLength + = maxNameLength + columnPadding + + maxRegionNameLength + columnPadding + + maxTypeLength + columnPadding; report.Append(GetColumnEntry("User", maxNameLength, columnPadding)); report.Append(GetColumnEntry("Region", maxRegionNameLength, columnPadding)); report.Append(GetColumnEntry("Type", maxTypeLength, columnPadding)); report.AppendFormat( - "{0,7} {1,7} {2,7} {3,9} {4,7} {5,7} {6,7} {7,7} {8,7} {9,8} {10,7} {11,7}\n", + "{0,7} {1,7} {2,7} {3,7} {4,9} {5,7} {6,7} {7,7} {8,7} {9,7} {10,8} {11,7} {12,7}\n", + "Since", + "Pkts", "Pkts", "Pkts", - "Pkts", "Bytes", "Q Pkts", "Q Pkts", @@ -396,7 +401,8 @@ namespace OpenSim.Region.CoreModules.UDP.Linden report.AppendFormat("{0,-" + totalInfoFieldsLength + "}", ""); report.AppendFormat( - "{0,7} {1,7} {2,7} {3,9} {4,7} {5,7} {6,7} {7,7} {8,7} {9,8} {10,7} {11,7}\n", + "{0,7} {1,7} {2,7} {3,7} {4,9} {5,7} {6,7} {7,7} {8,7} {9,7} {10,8} {11,7} {12,7}\n", + "Last In", "In", "Out", "Resent", @@ -417,22 +423,22 @@ namespace OpenSim.Region.CoreModules.UDP.Linden scene.ForEachClient( delegate(IClientAPI client) { - if (client is IStatsCollector) - { - bool isChild = client.SceneAgent.IsChildAgent; - if (isChild && !showChildren) - return; - - string name = client.Name; - if (pname != "" && name != pname) - return; + bool isChild = client.SceneAgent.IsChildAgent; + if (isChild && !showChildren) + return; + + string name = client.Name; + if (pname != "" && name != pname) + return; - string regionName = scene.RegionInfo.RegionName; - - report.Append(GetColumnEntry(name, maxNameLength, columnPadding)); - report.Append(GetColumnEntry(regionName, maxRegionNameLength, columnPadding)); - report.Append(GetColumnEntry(isChild ? "Cd" : "Rt", maxTypeLength, columnPadding)); + string regionName = scene.RegionInfo.RegionName; + + report.Append(GetColumnEntry(name, maxNameLength, columnPadding)); + report.Append(GetColumnEntry(regionName, maxRegionNameLength, columnPadding)); + report.Append(GetColumnEntry(isChild ? "Cd" : "Rt", maxTypeLength, columnPadding)); + if (client is IStatsCollector) + { IStatsCollector stats = (IStatsCollector)client; report.AppendLine(stats.Report()); -- cgit v1.1 From 1427430b7b0049ff4b312766737dc0e907c1c56d Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 24 Jul 2012 23:48:53 +0100 Subject: Add information about each column to "show queues" region console command help. --- .../OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs b/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs index 906c1d4..7c14c02 100644 --- a/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs +++ b/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs @@ -105,8 +105,15 @@ namespace OpenSim.Region.CoreModules.UDP.Linden "Comms", this, "show queues", "show queues [full]", "Show queue data for each client", - "Without the 'full' option, only root agents are shown." - + " With the 'full' option child agents are also shown.", + "Without the 'full' option, only root agents are shown.\n" + + "With the 'full' option child agents are also shown.\n\n" + + "Type - Rt is a root (avatar) client whilst cd is a child (neighbour interacting) client.\n" + + "Since Last In - Time in milliseconds since last packet received.\n" + + "Pkts In - Number of packets processed from the client.\n" + + "Pkts Out - Number of packets sent to the client.\n" + + "Pkts Resent - Number of packets resent to the client.\n" + + "Bytes Unacked - Number of bytes transferred to the client that are awaiting acknowledgement.\n" + + "Q Pkts * - Number of packets of various types (land, wind, etc.) to be sent to the client that are waiting for available bandwidth.\n", (mod, cmd) => MainConsole.Instance.Output(GetQueuesReport(cmd))); scene.AddCommand( -- cgit v1.1 From 3cf8edfd681b3372fb5ecde96d88d4f20fcdcefa Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 24 Jul 2012 23:51:04 +0100 Subject: Rename "image queues clear" console command to "clear image queues" There is less justification for this word arrangement (verb after noun) now that command help is categorized. Also removes "image queues show" in favour of existing alias "show image queues". --- .../Agent/UDP/Linden/LindenUDPInfoModule.cs | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs b/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs index 7c14c02..ca9bd4a 100644 --- a/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs +++ b/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs @@ -82,18 +82,6 @@ namespace OpenSim.Region.CoreModules.UDP.Linden m_scenes[scene.RegionInfo.RegionID] = scene; scene.AddCommand( - "Comms", this, "image queues clear", - "image queues clear ", - "Clear the image queues (textures downloaded via UDP) for a particular client.", - (mod, cmd) => MainConsole.Instance.Output(HandleImageQueuesClear(cmd))); - - scene.AddCommand( - "Comms", this, "image queues show", - "image queues show ", - "Show the image queues (textures downloaded via UDP) for a particular client.", - (mod, cmd) => MainConsole.Instance.Output(GetImageQueuesReport(cmd))); - - scene.AddCommand( "Comms", this, "show pqueues", "show pqueues [full]", "Show priority queue data for each client", @@ -121,6 +109,12 @@ namespace OpenSim.Region.CoreModules.UDP.Linden "show image queues ", "Show the image queues (textures downloaded via UDP) for a particular client.", (mod, cmd) => MainConsole.Instance.Output(GetImageQueuesReport(cmd))); + + scene.AddCommand( + "Comms", this, "clear image queues", + "clear image queues ", + "Clear the image queues (textures downloaded via UDP) for a particular client.", + (mod, cmd) => MainConsole.Instance.Output(HandleImageQueuesClear(cmd))); scene.AddCommand( "Comms", this, "show throttles", -- cgit v1.1 From af05aaaf36c402cd774acd62893113681596474c Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 25 Jul 2012 01:28:11 +0100 Subject: Remove support for the OS_NPC constant. That one seems to be overly paranoid to have and confuses the issue. --- .../ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs | 5 ++--- OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs | 1 - 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs index f7314da..19f3ce1 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs @@ -68,7 +68,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins private const int AGENT = 1; private const int AGENT_BY_USERNAME = 0x10; private const int NPC = 0x20; - private const int OS_NPC = 0x01000000; private const int ACTIVE = 2; private const int PASSIVE = 4; private const int SCRIPTED = 8; @@ -221,7 +220,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins List sensedEntities = new List(); // Is the sensor type is AGENT and not SCRIPTED then include agents - if ((ts.type & (AGENT | AGENT_BY_USERNAME | NPC | OS_NPC)) != 0 && (ts.type & SCRIPTED) == 0) + if ((ts.type & (AGENT | AGENT_BY_USERNAME | NPC)) != 0 && (ts.type & SCRIPTED) == 0) { sensedEntities.AddRange(doAgentSensor(ts)); } @@ -485,7 +484,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins // "[SENSOR REPEAT]: Inspecting scene presence {0}, type {1} on sensor sweep for {2}, type {3}", // presence.Name, presence.PresenceType, ts.name, ts.type); - if ((ts.type & NPC) == 0 && (ts.type & OS_NPC) == 0 && presence.PresenceType == PresenceType.Npc) + if ((ts.type & NPC) == 0 && presence.PresenceType == PresenceType.Npc) { INPC npcData = npcModule.GetNPC(presence.UUID, presence.Scene); if (npcData == null || !npcData.SenseAsAgent) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs index 5669917..a08cc42 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs @@ -56,7 +56,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase public const int ACTIVE = 2; public const int PASSIVE = 4; public const int SCRIPTED = 8; - public const int OS_NPC = 0x01000000; public const int CONTROL_FWD = 1; public const int CONTROL_BACK = 2; -- cgit v1.1 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 From 45b72bf01c99697e65b6cda5515bbadc4a9442da Mon Sep 17 00:00:00 2001 From: Melanie Date: Sat, 28 Jul 2012 01:06:28 +0100 Subject: Fix some merge issues and a functional issue in the scene manager --- OpenSim/Region/Framework/Scenes/SceneManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Framework/Scenes/SceneManager.cs b/OpenSim/Region/Framework/Scenes/SceneManager.cs index a412414..f1b09ca 100644 --- a/OpenSim/Region/Framework/Scenes/SceneManager.cs +++ b/OpenSim/Region/Framework/Scenes/SceneManager.cs @@ -192,7 +192,7 @@ namespace OpenSim.Region.Framework.Scenes private void HandleRegionReadyStatusChange(IScene scene) { lock (m_localScenes) - AllRegionsReady = m_localScenes.TrueForAll(s => s.Ready); + AllRegionsReady = m_localScenes.FindAll(s => !s.Ready).Count == 0; } public void SendSimOnlineNotification(ulong regionHandle) -- cgit v1.1 From 3f6dfa92ab46bafbb1947f441aa1386d87c4576b Mon Sep 17 00:00:00 2001 From: Melanie Date: Sun, 29 Jul 2012 16:05:35 +0100 Subject: Return world rotation on llGetObjectDetails()'s OBJECT_ROT --- .../Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 084bd41..c3b1f3d 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -10446,7 +10446,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api ret.Add(new LSL_Vector(obj.AbsolutePosition.X, obj.AbsolutePosition.Y, obj.AbsolutePosition.Z)); break; case ScriptBaseClass.OBJECT_ROT: - ret.Add(new LSL_Rotation(obj.RotationOffset.X, obj.RotationOffset.Y, obj.RotationOffset.Z, obj.RotationOffset.W)); + { + Quaternion rot = Quaternion.Identity; + + if (obj.ParentGroup.RootPart == obj) + rot = obj.ParentGroup.GroupRotation; + else + rot = obj.GetWorldRotation(); + + LSL_Rotation objrot = new LSL_Rotation(rot.X, rot.Y, rot.Z, rot.W); + ret.Add(objrot); + } break; case ScriptBaseClass.OBJECT_VELOCITY: ret.Add(new LSL_Vector(obj.Velocity.X, obj.Velocity.Y, obj.Velocity.Z)); -- cgit v1.1 From b899d64dc16a24ca8c221c4883f0cdb0f1a5ab26 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 30 Jul 2012 23:14:20 +0100 Subject: If we're fetching active gestures via the XInventoryServiceConnector, then properly look at the ITEMS dictionary already returned rather than the level above this. --- OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim') diff --git a/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs b/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs index 9d96703..fe7a799 100644 --- a/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs +++ b/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs @@ -474,7 +474,7 @@ namespace OpenSim.Services.Connectors List items = new List(); - foreach (Object o in ret.Values) // getting the values directly, we don't care about the keys item_i + foreach (Object o in ((Dictionary)ret["ITEMS"]).Values) items.Add(BuildItem((Dictionary)o)); return items; -- cgit v1.1 From 50dbb9ffe480b08f13f7bebb8259193dc00f88dd Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Tue, 31 Jul 2012 09:23:05 -0700 Subject: BulletSim: add parameters and API calls for setting ERP and CFM. Set ERP and CFM in linkset constraints. Reorder rebuilding of object bodies so they are not rebuilt everytime something is linked and unlinked. --- .../Region/Physics/BulletSPlugin/BSConstraint.cs | 12 ++++- .../BulletSPlugin/BSConstraintCollection.cs | 8 +++- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 56 +++++++++++++++++++--- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 38 ++++++++++----- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 34 ++++++++++++- .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 45 +++++++++++++---- 6 files changed, 164 insertions(+), 29 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs index fbb9e21..07f5a21 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs @@ -50,7 +50,8 @@ public class BSConstraint : IDisposable m_body2 = obj2; m_constraint = new BulletConstraint(BulletSimAPI.CreateConstraint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr, frame1, frame1rot, - frame2, frame2rot)); + frame2, frame2rot, + true /*useLinearReferenceFrameA*/, true /*disableCollisionsBetweenLinkedBodies*/)); m_enabled = true; } @@ -83,6 +84,15 @@ public class BSConstraint : IDisposable return ret; } + public bool SetCFMAndERP(float cfm, float erp) + { + bool ret = false; + BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL); + BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_ERP, erp, ConstraintParamAxis.AXIS_ALL); + BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_CFM, cfm, ConstraintParamAxis.AXIS_ALL); + return ret; + } + public bool UseFrameOffset(bool useOffset) { bool ret = false; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs index a2650fb..c88e645 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs @@ -83,7 +83,8 @@ public class BSConstraintCollection : IDisposable return true; } - // Get the constraint between two bodies. There can be only one the way we're using them. + // Get the constraint between two bodies. There can be only one. + // Return 'true' if a constraint was found. public bool TryGetConstraint(BulletBody body1, BulletBody body2, out BSConstraint returnConstraint) { bool found = false; @@ -105,6 +106,9 @@ public class BSConstraintCollection : IDisposable return found; } + // Remove any constraint between the passed bodies. + // Presumed there is only one such constraint possible. + // Return 'true' if a constraint was found and destroyed. public bool RemoveAndDestroyConstraint(BulletBody body1, BulletBody body2) { // return BulletSimAPI.RemoveConstraint(m_world.ID, obj1.ID, obj2.ID); @@ -125,6 +129,8 @@ public class BSConstraintCollection : IDisposable return ret; } + // Remove all constraints that reference the passed body. + // Return 'true' if any constraints were destroyed. public bool RemoveAndDestroyConstraint(BulletBody body1) { // return BulletSimAPI.RemoveConstraintByID(m_world.ID, obj.ID); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 3bc2100..6f8430c 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -117,10 +117,50 @@ public class BSLinkset } // 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) + // Go through the linkset and rebuild the pointers to the bodies of the linkset members. + public BSLinkset RefreshLinkset(BSPrim requestor) { - return true; + BSLinkset ret = requestor.Linkset; + + lock (m_linksetActivityLock) + { + System.IntPtr aPtr = BulletSimAPI.GetBodyHandle2(m_scene.World.Ptr, m_linksetRoot.LocalID); + if (aPtr == System.IntPtr.Zero) + { + // That's odd. We can't find the root of the linkset. + // The linkset is somehow dead. The requestor is now a member of a linkset of one. + DetailLog("{0},RefreshLinkset.RemoveRoot,child={1}", m_linksetRoot.LocalID, m_linksetRoot.LocalID); + ret = RemoveMeFromLinkset(m_linksetRoot); + } + else + { + // Reconstruct the pointer to the body of the linkset root. + DetailLog("{0},RefreshLinkset.RebuildRoot,rootID={1},ptr={2}", m_linksetRoot.LocalID, m_linksetRoot.LocalID, aPtr); + m_linksetRoot.Body = new BulletBody(m_linksetRoot.LocalID, aPtr); + + List toRemove = new List(); + foreach (BSPrim bsp in m_children) + { + aPtr = BulletSimAPI.GetBodyHandle2(m_scene.World.Ptr, bsp.LocalID); + if (aPtr == System.IntPtr.Zero) + { + toRemove.Add(bsp); + } + else + { + // Reconstruct the pointer to the body of the linkset root. + DetailLog("{0},RefreshLinkset.RebuildChild,rootID={1},ptr={2}", bsp.LocalID, m_linksetRoot.LocalID, aPtr); + bsp.Body = new BulletBody(bsp.LocalID, aPtr); + } + } + foreach (BSPrim bsp in toRemove) + { + RemoveChildFromLinkset(bsp); + } + } + } + + return ret; } @@ -256,10 +296,13 @@ public class BSLinkset 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, + // childRelativePosition, + // childRelativeRotation, + OMV.Vector3.Zero, + OMV.Quaternion.Identity, OMV.Vector3.Zero, - OMV.Quaternion.Identity); + OMV.Quaternion.Identity + ); constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); @@ -268,6 +311,7 @@ public class BSLinkset constrain.TranslationalLimitMotor(m_scene.BoolNumeric(m_scene.Params.linkConstraintEnableTransMotor), m_scene.Params.linkConstraintTransMotorMaxVel, m_scene.Params.linkConstraintTransMotorMaxForce); + constrain.SetCFMAndERP(m_scene.Params.linkConstraintCFM, m_scene.Params.linkConstraintERP); } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 7590d93..50d11e6 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -103,7 +103,10 @@ public sealed class BSPrim : PhysicsActor long _collidingGroundStep; private BulletBody m_body; - public BulletBody Body { get { return m_body; } } + public BulletBody Body { + get { return m_body; } + set { m_body = value; } + } private BSDynamics _vehicle; @@ -477,9 +480,11 @@ public sealed class BSPrim : PhysicsActor // Only called at taint time so it is save to call into Bullet. private void SetObjectDynamic() { - // m_log.DebugFormat("{0}: ID={1}, SetObjectDynamic: IsStatic={2}, IsSolid={3}", LogHeader, _localID, IsStatic, IsSolid); - - RecreateGeomAndObject(); + // RA: remove this for the moment. + // The problem is that dynamic objects are hulls so if we are becoming physical + // the shape has to be checked and possibly built. + // Maybe a VerifyCorrectPhysicalShape() routine? + // RecreateGeomAndObject(); float mass = _mass; // Bullet wants static objects have a mass of zero @@ -971,21 +976,23 @@ public sealed class BSPrim : PhysicsActor { 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; + // TODO: do we need to check for and destroy a mesh or hull that might have been left from before? + ret = true; } } } else { - // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, size={2}", LogHeader, LocalID, _size); + // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, type={2}, size={3}", LogHeader, LocalID, _shapeType, _size); if (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX) { DetailLog("{0},CreateGeom,box", LocalID); _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX; - ret = true; _scale = _size; + // TODO: do we need to check for and destroy a mesh or hull that might have been left from before? + ret = true; } } } @@ -1203,11 +1210,9 @@ public sealed class BSPrim : PhysicsActor 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 @@ -1236,8 +1241,8 @@ public sealed class BSPrim : PhysicsActor private void RecreateGeomAndObject() { // m_log.DebugFormat("{0}: RecreateGeomAndObject. lID={1}", LogHeader, _localID); - CreateGeom(true); - CreateObject(); + if (CreateGeom(true)) + CreateObject(); return; } @@ -1322,6 +1327,15 @@ public sealed class BSPrim : PhysicsActor base.RequestPhysicsterseUpdate(); } + /* + else + { + // For debugging, we can also report the movement of children + DetailLog("{0},UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}", + LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, + entprop.Acceleration, entprop.RotationalVelocity); + } + */ } // I've collided with something diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index c6d622b..28d5cb5 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -315,6 +315,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters public override PhysicsActor AddAvatar(uint localID, string avName, Vector3 position, Vector3 size, bool isFlying) { // m_log.DebugFormat("{0}: AddAvatar: {1}", LogHeader, avName); + + if (!m_initialized) return null; + BSCharacter actor = new BSCharacter(localID, avName, this, position, size, isFlying); lock (m_avatars) m_avatars.Add(localID, actor); return actor; @@ -323,6 +326,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters public override void RemoveAvatar(PhysicsActor actor) { // m_log.DebugFormat("{0}: RemoveAvatar", LogHeader); + + if (!m_initialized) return; + BSCharacter bsactor = actor as BSCharacter; if (bsactor != null) { @@ -341,6 +347,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters public override void RemovePrim(PhysicsActor prim) { + if (!m_initialized) return; + BSPrim bsprim = prim as BSPrim; if (bsprim != null) { @@ -366,6 +374,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters Vector3 size, Quaternion rotation, bool isPhysical, uint localID) { // m_log.DebugFormat("{0}: AddPrimShape2: {1}", LogHeader, primName); + + if (!m_initialized) return null; + BSPrim prim = new BSPrim(localID, primName, this, position, size, rotation, pbs, isPhysical); lock (m_prims) m_prims.Add(localID, prim); return prim; @@ -807,6 +818,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters // List of all of the externally visible parameters. // For each parameter, this table maps a text name to getter and setters. + // To add a new externally referencable/settable parameter, add the paramter storage + // location somewhere in the program and make an entry in this table with the + // getters and setters. + // To add a new variable, it is easiest to find an existing definition and copy it. + // Parameter values are floats. Booleans are converted to a floating value. + // // 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. @@ -815,7 +832,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters // -- 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. + // The single letter parameters for the delegates are: + // s = BSScene + // p = string parameter name + // l = localID of referenced object + // v = float value + // cf = parameter configuration class (for fetching values from ini file) private ParameterDefn[] ParameterDefinitions = { new ParameterDefn("MeshSculptedPrim", "Whether to create meshes for sculpties", @@ -1048,6 +1070,16 @@ public class BSScene : PhysicsScene, IPhysicsParameters (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("LinkConstraintCFM", "Amount constraint can be violated. 0=none, 1=all. Default=0", + 0.0f, + (s,cf,p,v) => { s.m_params[0].linkConstraintCFM = cf.GetFloat(p, v); }, + (s) => { return s.m_params[0].linkConstraintCFM; }, + (s,p,l,v) => { s.m_params[0].linkConstraintCFM = v; } ), + new ParameterDefn("LinkConstraintERP", "Amount constraint is corrected each tick. 0=none, 1=all. Default = 0.2", + 0.2f, + (s,cf,p,v) => { s.m_params[0].linkConstraintERP = cf.GetFloat(p, v); }, + (s) => { return s.m_params[0].linkConstraintERP; }, + (s,p,l,v) => { s.m_params[0].linkConstraintERP = v; } ), new ParameterDefn("DetailedStats", "Frames between outputting detailed phys stats. (0 is off)", 0f, diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 65e3145..fe705cc 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -66,13 +66,14 @@ public struct ShapeData { public enum PhysicsShapeType { - SHAPE_AVATAR = 0, - SHAPE_BOX = 1, - SHAPE_CONE = 2, - SHAPE_CYLINDER = 3, - SHAPE_SPHERE = 4, - SHAPE_MESH = 5, - SHAPE_HULL = 6 + SHAPE_UNKNOWN = 0, + SHAPE_AVATAR = 1, + SHAPE_BOX = 2, + SHAPE_CONE = 3, + SHAPE_CYLINDER = 4, + SHAPE_SPHERE = 5, + SHAPE_MESH = 6, + SHAPE_HULL = 7 }; public uint ID; public PhysicsShapeType Type; @@ -168,6 +169,8 @@ public struct ConfigurationParameters public float linkConstraintEnableTransMotor; public float linkConstraintTransMotorMaxVel; public float linkConstraintTransMotorMaxForce; + public float linkConstraintERP; + public float linkConstraintCFM; public const float numericTrue = 1f; public const float numericFalse = 0f; @@ -189,6 +192,28 @@ public enum CollisionFlags : uint PHYSICAL_OBJECT = 1 << 12, }; +// CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0 +// ERP controls amount of correction per tick. Usable range=0.1..0.8. Default=0.2. +public enum ConstraintParams : int +{ + BT_CONSTRAINT_ERP = 1, // this one is not used in Bullet as of 20120730 + BT_CONSTRAINT_STOP_ERP, + BT_CONSTRAINT_CFM, + BT_CONSTRAINT_STOP_CFM, +}; +public enum ConstraintParamAxis : int +{ + AXIS_LINEAR_X = 0, + AXIS_LINEAR_Y, + AXIS_LINEAR_Z, + AXIS_ANGULAR_X, + AXIS_ANGULAR_Y, + AXIS_ANGULAR_Z, + AXIS_LINEAR_ALL = 20, // these last three added by BulletSim so we don't have to do zillions of calls + AXIS_ANGULAR_ALL, + AXIS_ALL +}; + // =============================================================================== static class BulletSimAPI { @@ -380,7 +405,8 @@ 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 frame2loc, Quaternion frame2rot, + bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern bool SetLinearLimits2(IntPtr constrain, Vector3 low, Vector3 hi); @@ -398,6 +424,9 @@ public static extern bool TranslationalLimitMotor2(IntPtr constrain, float enabl public static extern bool CalculateTransforms2(IntPtr constrain); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool SetConstraintParam2(IntPtr constrain, ConstraintParams paramIndex, float value, ConstraintParamAxis axis); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern bool DestroyConstraint2(IntPtr sim, IntPtr constrain); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -- cgit v1.1 From a76a289d11086dd99d345390e58a43b66b053470 Mon Sep 17 00:00:00 2001 From: Mic Bowman Date: Tue, 31 Jul 2012 10:45:37 -0700 Subject: Adds support to ScriptModuleComms for region modules to export constants to the script engine. --- .../Framework/Interfaces/IScriptModuleComms.cs | 4 +++ .../ScriptModuleComms/ScriptModuleCommsModule.cs | 33 ++++++++++++++++++ .../Shared/CodeTools/CSCodeGenerator.cs | 39 ++++++++++++++++++++-- 3 files changed, 74 insertions(+), 2 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs b/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs index bfe1e8d..ed71a95 100644 --- a/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs +++ b/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs @@ -67,6 +67,10 @@ namespace OpenSim.Region.Framework.Interfaces /// void DispatchReply(UUID scriptId, int code, string text, string key); + /// For constants + void RegisterConstant(string cname, object value); + object LookupModConstant(string cname); + // For use ONLY by the script API void RaiseEvent(UUID script, string id, string module, string command, string key); } diff --git a/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs index 74a85e2..705a847 100644 --- a/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs @@ -46,6 +46,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private Dictionary m_constants = new Dictionary(); + #region ScriptInvocation protected class ScriptInvocationData { @@ -269,6 +271,37 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms Delegate fn = LookupScriptInvocation(fname); return fn.DynamicInvoke(olist.ToArray()); } + + /// + /// Operation to for a region module to register a constant to be used + /// by the script engine + /// + public void RegisterConstant(string cname, object value) + { + m_log.DebugFormat("[MODULE COMMANDS] register constant <{0}> with value {1}",cname,value.ToString()); + lock (m_constants) + { + m_constants.Add(cname,value); + } + } + + /// + /// Operation to check for a registered constant + /// + public object LookupModConstant(string cname) + { + // m_log.DebugFormat("[MODULE COMMANDS] lookup constant <{0}>",cname); + + lock (m_constants) + { + object value = null; + if (m_constants.TryGetValue(cname,out value)) + return value; + } + + return null; + } + #endregion } diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs index b24f016..97dd0f6 100644 --- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs +++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs @@ -38,7 +38,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools { public class CSCodeGenerator : ICodeConverter { -// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); +// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private SYMBOL m_astRoot = null; private Dictionary, KeyValuePair> m_positionMap; @@ -255,7 +255,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools else if (s is IdentDotExpression) retstr += Generate(CheckName(((IdentDotExpression) s).Name) + "." + ((IdentDotExpression) s).Member, s); else if (s is IdentExpression) - retstr += Generate(CheckName(((IdentExpression) s).Name), s); + retstr += GenerateIdentifier(((IdentExpression) s).Name, s); else if (s is IDENT) retstr += Generate(CheckName(((TOKEN) s).yytext), s); else @@ -868,6 +868,41 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools } /// + /// Generates the code for an identifier + /// + /// The symbol name + /// The Symbol node. + /// String containing C# code for identifier reference. + private string GenerateIdentifier(string id, SYMBOL s) + { + if (m_comms != null) + { + object value = m_comms.LookupModConstant(id); + if (value != null) + { + string retval = null; + if (value is int) + retval = ((int)value).ToString(); + else if (value is float) + retval = String.Format("new LSL_Types.LSLFloat({0})",((float)value).ToString()); + else if (value is string) + retval = String.Format("new LSL_Types.LSLString(\"{0}\")",((string)value)); + else if (value is OpenMetaverse.UUID) + retval = String.Format("new LSL_Types.key(\"{0}\")",((OpenMetaverse.UUID)value).ToString()); + else if (value is OpenMetaverse.Vector3) + retval = String.Format("new LSL_Types.Vector3(\"{0}\")",((OpenMetaverse.Vector3)value).ToString()); + else if (value is OpenMetaverse.Quaternion) + retval = String.Format("new LSL_Types.Quaternion(\"{0}\")",((OpenMetaverse.Quaternion)value).ToString()); + else retval = id; + + return Generate(retval, s); + } + } + + return Generate(CheckName(id), s); + } + + /// /// Generates the code for a FunctionCall node. /// /// The FunctionCall node. -- cgit v1.1 From d89faa3c16833a78bb6af3defa5c7bf272b55e1c Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 31 Jul 2012 22:52:17 +0100 Subject: Fix bug in SoundModule.TriggerSound() where every sound update to an avatar would base its gain calculation on the previous avatar's gain, instead of the original input gain. This was making sound attenuate oddly when there were NPCs in the region, though it could also happen with ordinary avatars. --- OpenSim/Region/CoreModules/World/Sound/SoundModule.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs index d768a1a..14c1a39 100644 --- a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs +++ b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs @@ -119,17 +119,20 @@ namespace OpenSim.Region.CoreModules.World.Sound m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) { double dis = Util.GetDistanceTo(sp.AbsolutePosition, position); + if (dis > 100.0) // Max audio distance return; + float thisSpGain; + // Scale by distance if (radius == 0) - gain = (float)((double)gain * ((100.0 - dis) / 100.0)); + thisSpGain = (float)((double)gain * ((100.0 - dis) / 100.0)); else - gain = (float)((double)gain * ((radius - dis) / radius)); + thisSpGain = (float)((double)gain * ((radius - dis) / radius)); sp.ControllingClient.SendTriggeredSound( - soundId, ownerID, objectID, parentID, handle, position, (float)gain); + soundId, ownerID, objectID, parentID, handle, position, thisSpGain); }); } } -- cgit v1.1 From 7609daca388d1acbe8da7eaf407c0b3f4da1fd80 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 31 Jul 2012 23:57:57 +0100 Subject: Resolve a deadlock between INPCModule and SensorRepeat by replacing the SensorRepeat list with a new list on add/removes rather than locking it for the duration of the sensor sweep. A deadlock was observed today where NPC removal on a script thread would lock the NPC list and then try to lock the sensor list via scripted attachment removal. Concurrently, the sensor sweep thread would lock the sensor list and then try to lock the NPC list to check NPC status. This commit resolves the deadlock by replacing the sensor list on update rather than locking it for the duration of the sweep. --- .../Api/Implementation/Plugins/SensorRepeat.cs | 78 ++++++++++++---------- 1 file changed, 43 insertions(+), 35 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs index f2c8b60..06495bb 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs @@ -51,8 +51,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins { get { - lock (SenseRepeatListLock) - return SenseRepeaters.Count; + return SenseRepeaters.Count; } } @@ -116,6 +115,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins public double distance; } + /// + /// Sensors to process. + /// + /// + /// Do not add or remove sensors from this list directly. Instead, copy the list and substitute the updated + /// copy. This is to avoid locking the list for the duration of the sensor sweep, which increases the danger + /// of deadlocks with future code updates. + /// + /// Always lock SenseRepeatListLock when updating this list. + /// private List SenseRepeaters = new List(); private object SenseRepeatListLock = new object(); @@ -125,6 +134,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins { // Always remove first, in case this is a re-set UnSetSenseRepeaterEvents(m_localID, m_itemID); + if (sec == 0) // Disabling timer return; @@ -144,9 +154,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins ts.host = host; ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval); + + AddSenseRepeater(ts); + } + + private void AddSenseRepeater(SenseRepeatClass senseRepeater) + { lock (SenseRepeatListLock) { - SenseRepeaters.Add(ts); + List newSenseRepeaters = new List(SenseRepeaters); + newSenseRepeaters.Add(senseRepeater); + SenseRepeaters = newSenseRepeaters; } } @@ -155,39 +173,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins // Remove from timer lock (SenseRepeatListLock) { - List NewSensors = new List(); + List newSenseRepeaters = new List(); foreach (SenseRepeatClass ts in SenseRepeaters) { if (ts.localID != m_localID || ts.itemID != m_itemID) { - NewSensors.Add(ts); + newSenseRepeaters.Add(ts); } } - SenseRepeaters.Clear(); - SenseRepeaters = NewSensors; + + SenseRepeaters = newSenseRepeaters; } } public void CheckSenseRepeaterEvents() { - lock (SenseRepeatListLock) + // Go through all timers + foreach (SenseRepeatClass ts in SenseRepeaters) { - // Nothing to do here? - if (SenseRepeaters.Count == 0) - return; - - // Go through all timers - foreach (SenseRepeatClass ts in SenseRepeaters) + // Time has passed? + if (ts.next.ToUniversalTime() < DateTime.Now.ToUniversalTime()) { - // Time has passed? - if (ts.next.ToUniversalTime() < DateTime.Now.ToUniversalTime()) - { - SensorSweep(ts); - // set next interval - ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval); - } + SensorSweep(ts); + // set next interval + ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval); } - } // lock + } } public void SenseOnce(uint m_localID, UUID m_itemID, @@ -615,21 +626,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins { List data = new List(); - lock (SenseRepeatListLock) + foreach (SenseRepeatClass ts in SenseRepeaters) { - foreach (SenseRepeatClass ts in SenseRepeaters) + if (ts.itemID == itemID) { - if (ts.itemID == itemID) - { - data.Add(ts.interval); - data.Add(ts.name); - data.Add(ts.keyID); - data.Add(ts.type); - data.Add(ts.range); - data.Add(ts.arc); - } + data.Add(ts.interval); + data.Add(ts.name); + data.Add(ts.keyID); + data.Add(ts.type); + data.Add(ts.range); + data.Add(ts.arc); } } + return data.ToArray(); } @@ -663,8 +672,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval); - lock (SenseRepeatListLock) - SenseRepeaters.Add(ts); + AddSenseRepeater(ts); idx += 6; } -- cgit v1.1 From 04d8c6b4fe22773eba6359c0ac71fe1f535ba211 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 1 Aug 2012 00:11:21 +0100 Subject: Change exception log messages in XInventoryService connector to error rather than debug, since these signal real problems. Also outputs full exception instead of just the message to aid diagnostics. --- .../Connectors/Inventory/XInventoryServicesConnector.cs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs b/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs index fe7a799..44f5e01 100644 --- a/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs +++ b/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs @@ -122,7 +122,7 @@ namespace OpenSim.Services.Connectors } catch (Exception e) { - m_log.DebugFormat("[XINVENTORY CONNECTOR STUB]: Exception unwrapping folder list: {0}", e.Message); + m_log.Error("[XINVENTORY SERVICES CONNECTOR]: Exception unwrapping folder list: ", e); } return fldrs; @@ -191,7 +191,7 @@ namespace OpenSim.Services.Connectors } catch (Exception e) { - m_log.DebugFormat("[XINVENTORY CONNECTOR STUB]: Exception in GetFolderContent: {0}", e.Message); + m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: Exception in GetFolderContent: {0}", e.Message); } return inventory; @@ -432,7 +432,7 @@ namespace OpenSim.Services.Connectors } catch (Exception e) { - m_log.DebugFormat("[XINVENTORY CONNECTOR STUB]: Exception in GetItem: {0}", e.Message); + m_log.Error("[XINVENTORY SERVICES CONNECTOR]: Exception in GetItem: ", e); } return null; @@ -456,7 +456,7 @@ namespace OpenSim.Services.Connectors } catch (Exception e) { - m_log.DebugFormat("[XINVENTORY CONNECTOR STUB]: Exception in GetFolder: {0}", e.Message); + m_log.Error("[XINVENTORY SERVICES CONNECTOR]: Exception in GetFolder: ", e); } return null; @@ -525,7 +525,7 @@ namespace OpenSim.Services.Connectors } catch (Exception e) { - m_log.DebugFormat("[XINVENTORY CONNECTOR STUB]: Exception in GetUserInventory: {0}", e.Message); + m_log.Error("[XINVENTORY SERVICES CONNECTOR]: Exception in GetUserInventory: ", e); } return inventory; @@ -574,7 +574,7 @@ namespace OpenSim.Services.Connectors } catch (Exception e) { - m_log.DebugFormat("[XINVENTORY CONNECTOR STUB]: Exception building folder: {0}", e.Message); + m_log.Error("[XINVENTORY SERVICES CONNECTOR]: Exception building folder: ", e); } return folder; @@ -613,11 +613,10 @@ namespace OpenSim.Services.Connectors } catch (Exception e) { - m_log.DebugFormat("[XINVENTORY CONNECTOR STUB]: Exception building item: {0}", e.Message); + m_log.Error("[XINVENTORY CONNECTOR]: Exception building item: ", e); } return item; } - } -} +} \ No newline at end of file -- cgit v1.1 From e38d26a2dc35ce7bf904c58200912a65c05aa39d Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Tue, 31 Jul 2012 11:32:26 -0700 Subject: BulletSim: change boolean parameters in the shape data from int's to float's to be consistant with parameter data structure --- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 8 ++++++-- OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs | 10 +++++----- 2 files changed, 11 insertions(+), 7 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 50d11e6..758acdc 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -187,6 +187,7 @@ public sealed class BSPrim : PhysicsActor { _mass = CalculateMass(); // changing size changes the mass BulletSimAPI.SetObjectScaleMass(_scene.WorldID, _localID, _scale, (IsPhysical ? _mass : 0f), IsPhysical); + DetailLog("{0}: setSize: size={1}, mass={2}, physical={3}", LocalID, _size, _mass, IsPhysical); RecreateGeomAndObject(); }); } @@ -1201,7 +1202,8 @@ public sealed class BSPrim : PhysicsActor // Create an object in Bullet if it has not already been created // No locking here because this is done when the physics engine is not simulating - private void CreateObject() + // Returns 'true' if an object was actually created. + private bool CreateObject() { // this routine is called when objects are rebuilt. @@ -1209,10 +1211,12 @@ public sealed class BSPrim : PhysicsActor ShapeData shape; FillShapeInfo(out shape); // m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, _localID, shape.Type); - BulletSimAPI.CreateObject(_scene.WorldID, shape); + bool ret = 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); + + return ret; } // Copy prim's info into the BulletSim shape description structure diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index fe705cc..0ffbc94 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -87,12 +87,12 @@ public struct ShapeData public System.UInt64 MeshKey; public float Friction; public float Restitution; - public int Collidable; - public int Static; // true if a static object. Otherwise gravity, etc. + public float Collidable; // true of things bump into this + public float Static; // true if a static object. Otherwise gravity, etc. - // note that bools are passed as ints since bool size changes by language and architecture - public const int numericTrue = 1; - public const int numericFalse = 0; + // note that bools are passed as floats since bool size changes by language and architecture + public const float numericTrue = 1f; + public const float numericFalse = 0f; } [StructLayout(LayoutKind.Sequential)] public struct SweepHit -- cgit v1.1 From c51ef38e2d867d63d2d32b1a7d284033e60d9952 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Tue, 31 Jul 2012 16:22:50 -0700 Subject: BulletSim: fix problem where resizing a primary shape (cube or sphere) would not rebuild the physics mesh. Update the DLLs and SOs to latest version. --- OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs | 2 +- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs index 07f5a21..ea3093a 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs @@ -86,7 +86,7 @@ public class BSConstraint : IDisposable public bool SetCFMAndERP(float cfm, float erp) { - bool ret = false; + bool ret = true; BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL); BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_ERP, erp, ConstraintParamAxis.AXIS_ALL); BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_CFM, cfm, ConstraintParamAxis.AXIS_ALL); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 758acdc..a4ab702 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -973,7 +973,7 @@ 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); - if (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE) + if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE)) { DetailLog("{0},CreateGeom,sphere", LocalID); _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE; @@ -987,7 +987,7 @@ public sealed class BSPrim : PhysicsActor else { // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, type={2}, size={3}", LogHeader, LocalID, _shapeType, _size); - if (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX) + if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX)) { DetailLog("{0},CreateGeom,box", LocalID); _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX; @@ -1331,7 +1331,6 @@ public sealed class BSPrim : PhysicsActor base.RequestPhysicsterseUpdate(); } - /* else { // For debugging, we can also report the movement of children @@ -1339,7 +1338,6 @@ public sealed class BSPrim : PhysicsActor LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, entprop.Acceleration, entprop.RotationalVelocity); } - */ } // I've collided with something -- cgit v1.1 From 794363421d3739f1f1920b69ab1aaa438fa2b891 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 1 Aug 2012 00:39:37 +0100 Subject: Look up the NPC module when the SensorRepeat class is created, rather than on every single sensor sweep. --- .../Shared/Api/Implementation/Plugins/SensorRepeat.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs index 06495bb..a626be8 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs @@ -60,8 +60,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins m_CmdManager = CmdManager; maximumRange = CmdManager.m_ScriptEngine.Config.GetDouble("SensorMaxRange", 96.0d); maximumToReturn = CmdManager.m_ScriptEngine.Config.GetInt("SensorMaxResults", 16); + m_npcModule = m_CmdManager.m_ScriptEngine.World.RequestModuleInterface(); } + private INPCModule m_npcModule; + private Object SenseLock = new Object(); private const int AGENT = 1; @@ -450,8 +453,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins private List doAgentSensor(SenseRepeatClass ts) { - INPCModule npcModule = m_CmdManager.m_ScriptEngine.World.RequestModuleInterface(); - List sensedEntities = new List(); // If nobody about quit fast @@ -484,7 +485,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins bool attached = (SensePoint.ParentGroup.AttachmentPoint != 0); Vector3 toRegionPos; double dis; - + Action senseEntity = new Action(presence => { // m_log.DebugFormat( @@ -493,7 +494,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins if ((ts.type & NPC) == 0 && (ts.type & OS_NPC) == 0 && presence.PresenceType == PresenceType.Npc) { - INPC npcData = npcModule.GetNPC(presence.UUID, presence.Scene); + INPC npcData = m_npcModule.GetNPC(presence.UUID, presence.Scene); if (npcData == null || !npcData.SenseAsAgent) { // m_log.DebugFormat( @@ -511,7 +512,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins } else { - INPC npcData = npcModule.GetNPC(presence.UUID, presence.Scene); + INPC npcData = m_npcModule.GetNPC(presence.UUID, presence.Scene); if (npcData != null && npcData.SenseAsAgent) { // m_log.DebugFormat( -- cgit v1.1 From 5f500c89ce9df27910fa6007d4d87aa238a8a2ba Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 1 Aug 2012 22:30:34 +0100 Subject: Fix a bug in pCampbot grabbing behaviour where an exception would be thrown if the bot was not yet aware of any objects. --- OpenSim/Tools/pCampBot/Behaviours/GrabbingBehaviour.cs | 3 +++ 1 file changed, 3 insertions(+) (limited to 'OpenSim') diff --git a/OpenSim/Tools/pCampBot/Behaviours/GrabbingBehaviour.cs b/OpenSim/Tools/pCampBot/Behaviours/GrabbingBehaviour.cs index 701881e..66a336a 100644 --- a/OpenSim/Tools/pCampBot/Behaviours/GrabbingBehaviour.cs +++ b/OpenSim/Tools/pCampBot/Behaviours/GrabbingBehaviour.cs @@ -47,6 +47,9 @@ namespace pCampBot { Dictionary objects = Bot.Objects; + if (objects.Count <= 0) + return; + Primitive prim = objects.ElementAt(Bot.Random.Next(0, objects.Count - 1)).Value; // This appears to be a typical message sent when a viewer user clicks a clickable object -- cgit v1.1 From cf16ca9bdaad75d42213089e18c0ee8f8422bbd6 Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 1 Aug 2012 22:36:24 +0100 Subject: Create the ability for physics modules to request assets on demand by themselves. For that, the physics module simply calls RequestAssetMethod, which in turn points to Scene.PhysicsRequestAsset. This gives physics access to the asset system without introducing unwanted knowledge of the scene class. --- OpenSim/Region/Application/OpenSimBase.cs | 1 + OpenSim/Region/Framework/Scenes/Scene.cs | 16 ++++++++++++++++ OpenSim/Region/Physics/Manager/PhysicsScene.cs | 5 +++++ 3 files changed, 22 insertions(+) (limited to 'OpenSim') diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs index 4084741..37cfe1d 100644 --- a/OpenSim/Region/Application/OpenSimBase.cs +++ b/OpenSim/Region/Application/OpenSimBase.cs @@ -700,6 +700,7 @@ namespace OpenSim scene.LoadWorldMap(); scene.PhysicsScene = GetPhysicsScene(scene.RegionInfo.RegionName); + scene.PhysicsScene.RequestAssetMethod = scene.PhysicsRequestAsset; scene.PhysicsScene.SetTerrain(scene.Heightmap.GetFloatsSerialised()); scene.PhysicsScene.SetWaterLevel((float) regionInfo.RegionSettings.WaterHeight); diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index eb4ba41..c77457c 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -5421,5 +5421,21 @@ namespace OpenSim.Region.Framework.Scenes m_SpawnPoint = 1; return m_SpawnPoint - 1; } + + // Wrappers to get physics modules retrieve assets. Has to be done this way + // because we can't assign the asset service to physics directly - at the + // time physics are instantiated it's not registered but it will be by + // the time the first prim exists. + public void PhysicsRequestAsset(UUID assetID, AssetReceivedDelegate callback) + { + AssetService.Get(assetID.ToString(), callback, PhysicsAssetReceived); + } + + private void PhysicsAssetReceived(string id, Object sender, AssetBase asset) + { + AssetReceivedDelegate callback = (AssetReceivedDelegate)sender; + + callback(asset); + } } } diff --git a/OpenSim/Region/Physics/Manager/PhysicsScene.cs b/OpenSim/Region/Physics/Manager/PhysicsScene.cs index b32cd30..6a0558a 100644 --- a/OpenSim/Region/Physics/Manager/PhysicsScene.cs +++ b/OpenSim/Region/Physics/Manager/PhysicsScene.cs @@ -43,6 +43,9 @@ namespace OpenSim.Region.Physics.Manager public delegate void JointDeactivated(PhysicsJoint joint); public delegate void JointErrorMessage(PhysicsJoint joint, string message); // this refers to an "error message due to a problem", not "amount of joint constraint violation" + public delegate void RequestAssetDelegate(UUID assetID, AssetReceivedDelegate callback); + public delegate void AssetReceivedDelegate(AssetBase asset); + /// /// Contact result from a raycast. /// @@ -73,6 +76,8 @@ namespace OpenSim.Region.Physics.Manager get { return new NullPhysicsScene(); } } + public RequestAssetDelegate RequestAssetMethod { private get; set; } + public virtual void TriggerPhysicsBasedRestart() { physicsCrash handler = OnPhysicsCrash; -- cgit v1.1