From c9695a0a59cba91a184683efaa7802338d68e4bd Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 2 Aug 2013 00:00:00 +0100 Subject: [PATCH 01/33] Move experimental attachments throttling further down the chain so that multiple attachments changes (e.g. change outfit) are also throttled --- .../Avatar/Attachments/AttachmentsModule.cs | 31 +++++++++---------- bin/OpenSimDefaults.ini | 4 +-- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index 97477d49f1..675fccc6e5 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -53,8 +53,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments public int DebugLevel { get; set; } /// - /// Period to sleep per 100 prims in order to avoid CPU spikes when an avatar with many attachments logs in - /// or many avatars with a medium levels of attachments login simultaneously. + /// Period to sleep per 100 prims in order to avoid CPU spikes when an avatar with many attachments logs in/changes + /// outfit or many avatars with a medium levels of attachments login/change outfit simultaneously. /// /// /// A value of 0 will apply no pause. The pause is specified in milliseconds. @@ -319,19 +319,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments SceneObjectGroup objatt = RezSingleAttachmentFromInventoryInternal( sp, sp.PresenceType == PresenceType.Npc ? UUID.Zero : attach.ItemID, attach.AssetID, attachmentPt, true); - - - if (ThrottlePer100PrimsRezzed > 0) - { - int throttleMs = (int)Math.Round((float)objatt.PrimCount / 100 * ThrottlePer100PrimsRezzed); - - if (DebugLevel > 0) - m_log.DebugFormat( - "[ATTACHMENTS MODULE]: Throttling by {0}ms after rez of {1} with {2} prims for attachment to {3} on point {4} in {5}", - throttleMs, objatt.Name, objatt.PrimCount, sp.Name, attachmentPt, m_scene.Name); - - Thread.Sleep(throttleMs); - } } catch (Exception e) { @@ -1023,7 +1010,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments } if (tainted) - objatt.HasGroupChanged = true; + objatt.HasGroupChanged = true; + + if (ThrottlePer100PrimsRezzed > 0) + { + int throttleMs = (int)Math.Round((float)objatt.PrimCount / 100 * ThrottlePer100PrimsRezzed); + + if (DebugLevel > 0) + m_log.DebugFormat( + "[ATTACHMENTS MODULE]: Throttling by {0}ms after rez of {1} with {2} prims for attachment to {3} on point {4} in {5}", + throttleMs, objatt.Name, objatt.PrimCount, sp.Name, attachmentPt, m_scene.Name); + + Thread.Sleep(throttleMs); + } return objatt; } diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini index 2488bf16f0..d5d29ec674 100644 --- a/bin/OpenSimDefaults.ini +++ b/bin/OpenSimDefaults.ini @@ -710,8 +710,8 @@ Enabled = true ; Controls the number of milliseconds that are slept per 100 prims rezzed in attachments - ; Experimental setting to control CPU spiking when avatars with many attachments login - ; or when multiple avatars with medium level attachments login simultaneously. + ; Experimental setting to control CPU spiking when avatars with many attachments login/change outfit + ; or when multiple avatars with medium level attachments login/change outfit simultaneously. ; If 0 then no throttling is performed. ThrottlePer100PrimsRezzed = 0; From d4c506e453b1115142eac237d3a1c4f65fa36e26 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 2 Aug 2013 00:08:14 +0100 Subject: [PATCH 02/33] minor: replace veclist.Add(new Vector3(0,0,0)) with Vector3.Zero in InventoryAccessModules.RezObject() - structs are passed by value --- .../Framework/InventoryAccess/InventoryAccessModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index 1203192744..68e4e26f60 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -771,7 +771,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); objlist.Add(g); - veclist.Add(new Vector3(0, 0, 0)); + veclist.Add(Vector3.Zero); float offsetHeight = 0; pos = m_Scene.GetNewRezLocation( From 07e4958b19b0b9dc9e1955b79e735230ccc6ea6f Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Thu, 1 Aug 2013 20:40:13 -0700 Subject: [PATCH 03/33] Turn off edit beams when object is derezed while being edited. (mantis #6722) --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 17da0d93d5..456c8cc4af 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -1568,8 +1568,14 @@ namespace OpenSim.Region.Framework.Scenes // Here's where you get them. m_AgentControlFlags = flags; m_headrotation = agentData.HeadRotation; + byte oldState = State; State = agentData.State; + // We need to send this back to the client in order to stop the edit beams + if ((oldState & (uint)AgentState.Editing) != 0 && State == (uint)AgentState.None) + ControllingClient.SendAgentTerseUpdate(this); + + PhysicsActor actor = PhysicsActor; if (actor == null) { From 87ee0c395ed82f27c2a52b5023d8036eb7e355c9 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 2 Aug 2013 09:44:01 -0700 Subject: [PATCH 04/33] Fix problem with modInvoke defined integer constants being build into scripts as boxed integers rather than proper reference to a new LSLInteger. This fixes an exception when using a registered integer constant in a script. --- .../Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs | 4 ++-- .../Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs index 21bae27282..92dd8137d9 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs @@ -319,7 +319,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api object[] convertedParms = new object[parms.Length]; for (int i = 0; i < parms.Length; i++) - convertedParms[i] = ConvertFromLSL(parms[i],signature[i], fname); + convertedParms[i] = ConvertFromLSL(parms[i], signature[i], fname); // now call the function, the contract with the function is that it will always return // non-null but don't trust it completely @@ -444,7 +444,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } } - MODError(String.Format("{1}: parameter type mismatch; expecting {0}",type.Name, fname)); + MODError(String.Format("{0}: parameter type mismatch; expecting {1}, type(parm)={2}", fname, type.Name, lslparm.GetType())); return null; } diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs index 9e32f4031a..6aa717db03 100644 --- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs +++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs @@ -937,7 +937,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools { string retval = null; if (value is int) - retval = ((int)value).ToString(); + retval = String.Format("new LSL_Types.LSLInteger({0})",((int)value).ToString()); else if (value is float) retval = String.Format("new LSL_Types.LSLFloat({0})",((float)value).ToString()); else if (value is string) From 5bcccfc305ae4f5a74b9b816781a2a643daa23b3 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Thu, 1 Aug 2013 12:35:22 -0700 Subject: [PATCH 05/33] BulletSim: add BSLinkInfo structure to remember link specific information for each link in a linkset. Extend BSLinksetConstraint to create and use BSLinkInfo with the default static constraint. --- .../Region/Physics/BulletSPlugin/BSLinkset.cs | 51 +++-- .../BulletSPlugin/BSLinksetCompound.cs | 4 +- .../BulletSPlugin/BSLinksetConstraints.cs | 191 ++++++++++++------ 3 files changed, 167 insertions(+), 79 deletions(-) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 7f946662ad..9613fe05e9 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -70,6 +70,15 @@ public abstract class BSLinkset return ret; } + public class BSLinkInfo + { + public BSPrimLinkable member; + public BSLinkInfo(BSPrimLinkable pMember) + { + member = pMember; + } + } + public BSPrimLinkable LinksetRoot { get; protected set; } protected BSScene m_physicsScene { get; private set; } @@ -78,7 +87,8 @@ public abstract class BSLinkset public int LinksetID { get; private set; } // The children under the root in this linkset. - protected HashSet m_children; + // protected HashSet m_children; + protected Dictionary m_children; // We lock the diddling of linkset classes to prevent any badness. // This locks the modification of the instances of this class. Changes @@ -109,7 +119,7 @@ public abstract class BSLinkset m_nextLinksetID = 1; m_physicsScene = scene; LinksetRoot = parent; - m_children = new HashSet(); + m_children = new Dictionary(); LinksetMass = parent.RawMass; Rebuilding = false; @@ -170,17 +180,7 @@ public abstract class BSLinkset bool ret = false; lock (m_linksetActivityLock) { - ret = m_children.Contains(child); - /* Safer version but the above should work - foreach (BSPrimLinkable bp in m_children) - { - if (child.LocalID == bp.LocalID) - { - ret = true; - break; - } - } - */ + ret = m_children.ContainsKey(child); } return ret; } @@ -194,7 +194,24 @@ public abstract class BSLinkset lock (m_linksetActivityLock) { action(LinksetRoot); - foreach (BSPrimLinkable po in m_children) + foreach (BSPrimLinkable po in m_children.Keys) + { + if (action(po)) + break; + } + } + return ret; + } + + // Perform an action on each member of the linkset including root prim. + // Depends on the action on whether this should be done at taint time. + public delegate bool ForEachLinkInfoAction(BSLinkInfo obj); + public virtual bool ForEachLinkInfo(ForEachLinkInfoAction action) + { + bool ret = false; + lock (m_linksetActivityLock) + { + foreach (BSLinkInfo po in m_children.Values) { if (action(po)) break; @@ -364,7 +381,7 @@ public abstract class BSLinkset { lock (m_linksetActivityLock) { - foreach (BSPrimLinkable bp in m_children) + foreach (BSPrimLinkable bp in m_children.Keys) { mass += bp.RawMass; } @@ -382,7 +399,7 @@ public abstract class BSLinkset com = LinksetRoot.Position * LinksetRoot.RawMass; float totalMass = LinksetRoot.RawMass; - foreach (BSPrimLinkable bp in m_children) + foreach (BSPrimLinkable bp in m_children.Keys) { com += bp.Position * bp.RawMass; totalMass += bp.RawMass; @@ -401,7 +418,7 @@ public abstract class BSLinkset { com = LinksetRoot.Position; - foreach (BSPrimLinkable bp in m_children) + foreach (BSPrimLinkable bp in m_children.Keys) { com += bp.Position; } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs index 6359046ca8..53c35846b7 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs @@ -257,7 +257,7 @@ public sealed class BSLinksetCompound : BSLinkset { if (!HasChild(child)) { - m_children.Add(child); + m_children.Add(child, new BSLinkInfo(child)); DetailLog("{0},BSLinksetCompound.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID); @@ -353,7 +353,7 @@ public sealed class BSLinksetCompound : BSLinkset // Add the shapes of all the components of the linkset int memberIndex = 1; - ForEachMember(delegate(BSPrimLinkable cPrim) + ForEachMember((cPrim) => { if (IsRoot(cPrim)) { diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs index f17d698462..d98bf77342 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs @@ -36,6 +36,75 @@ public sealed class BSLinksetConstraints : BSLinkset { // private static string LogHeader = "[BULLETSIM LINKSET CONSTRAINTS]"; + public class BSLinkInfoConstraint : BSLinkInfo + { + public ConstraintType constraintType; + public BSConstraint constraint; + public OMV.Vector3 linearLimitLow; + public OMV.Vector3 linearLimitHigh; + public OMV.Vector3 angularLimitLow; + public OMV.Vector3 angularLimitHigh; + public bool useFrameOffset; + public bool enableTransMotor; + public float transMotorMaxVel; + public float transMotorMaxForce; + public float cfm; + public float erp; + public float solverIterations; + + public BSLinkInfoConstraint(BSPrimLinkable pMember) + : base(pMember) + { + constraint = null; + ResetToFixedConstraint(); + } + + // Set all the parameters for this constraint to a fixed, non-movable constraint. + public void ResetToFixedConstraint() + { + constraintType = ConstraintType.D6_CONSTRAINT_TYPE; + linearLimitLow = OMV.Vector3.Zero; + linearLimitHigh = OMV.Vector3.Zero; + angularLimitLow = OMV.Vector3.Zero; + angularLimitHigh = OMV.Vector3.Zero; + useFrameOffset = BSParam.LinkConstraintUseFrameOffset; + enableTransMotor = BSParam.LinkConstraintEnableTransMotor; + transMotorMaxVel = BSParam.LinkConstraintTransMotorMaxVel; + transMotorMaxForce = BSParam.LinkConstraintTransMotorMaxForce; + cfm = BSParam.LinkConstraintCFM; + erp = BSParam.LinkConstraintERP; + solverIterations = BSParam.LinkConstraintSolverIterations; + } + + // Given a constraint, apply the current constraint parameters to same. + public void SetConstraintParameters(BSConstraint constrain) + { + switch (constraintType) + { + case ConstraintType.D6_CONSTRAINT_TYPE: + BSConstraint6Dof constrain6dof = constrain as BSConstraint6Dof; + if (constrain6dof != null) + { + // zero linear and angular limits makes the objects unable to move in relation to each other + constrain6dof.SetLinearLimits(linearLimitLow, linearLimitHigh); + constrain6dof.SetAngularLimits(angularLimitLow, angularLimitHigh); + + // tweek the constraint to increase stability + constrain6dof.UseFrameOffset(useFrameOffset); + constrain6dof.TranslationalLimitMotor(enableTransMotor, transMotorMaxVel, transMotorMaxForce); + constrain6dof.SetCFMAndERP(cfm, erp); + if (solverIterations != 0f) + { + constrain6dof.SetSolverIterations(solverIterations); + } + } + break; + default: + break; + } + } + } + public BSLinksetConstraints(BSScene scene, BSPrimLinkable parent) : base(scene, parent) { } @@ -142,7 +211,7 @@ public sealed class BSLinksetConstraints : BSLinkset { if (!HasChild(child)) { - m_children.Add(child); + m_children.Add(child, new BSLinkInfoConstraint(child)); DetailLog("{0},BSLinksetConstraints.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID); @@ -190,73 +259,74 @@ public sealed class BSLinksetConstraints : BSLinkset } // Create a static constraint between the two passed objects - private BSConstraint BuildConstraint(BSPrimLinkable rootPrim, BSPrimLinkable childPrim) + private BSConstraint BuildConstraint(BSPrimLinkable rootPrim, BSLinkInfo li) { + BSLinkInfoConstraint liConstraint = li as BSLinkInfoConstraint; + if (liConstraint == null) + return null; + // Zero motion for children so they don't interpolate - childPrim.ZeroMotion(true); + li.member.ZeroMotion(true); - // Relative position normalized to the root prim - // Essentually a vector pointing from center of rootPrim to center of childPrim - OMV.Vector3 childRelativePosition = childPrim.Position - rootPrim.Position; + BSConstraint constrain = null; - // real world coordinate of midpoint between the two objects - OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2); + switch (liConstraint.constraintType) + { + case ConstraintType.D6_CONSTRAINT_TYPE: + // Relative position normalized to the root prim + // Essentually a vector pointing from center of rootPrim to center of li.member + OMV.Vector3 childRelativePosition = liConstraint.member.Position - rootPrim.Position; - DetailLog("{0},BSLinksetConstraint.BuildConstraint,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}", - rootPrim.LocalID, - rootPrim.LocalID, rootPrim.PhysBody.AddrString, - childPrim.LocalID, childPrim.PhysBody.AddrString, - rootPrim.Position, childPrim.Position, midPoint); + // real world coordinate of midpoint between the two objects + OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2); - // create a constraint that allows no freedom of movement between the two objects - // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 + DetailLog("{0},BSLinksetConstraint.BuildConstraint,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}", + rootPrim.LocalID, + rootPrim.LocalID, rootPrim.PhysBody.AddrString, + liConstraint.member.LocalID, liConstraint.member.PhysBody.AddrString, + rootPrim.Position, liConstraint.member.Position, midPoint); - BSConstraint6Dof constrain = new BSConstraint6Dof( - m_physicsScene.World, rootPrim.PhysBody, childPrim.PhysBody, midPoint, true, true ); - // PhysicsScene.World, childPrim.BSBody, rootPrim.BSBody, midPoint, true, true ); + // create a constraint that allows no freedom of movement between the two objects + // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 - /* NOTE: below is an attempt to build constraint with full frame computation, etc. - * Using the midpoint is easier since it lets the Bullet code manipulate the transforms - * of the objects. - * Code left for future programmers. - // ================================================================================== - // relative position normalized to the root prim - OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation); - OMV.Vector3 childRelativePosition = (childPrim.Position - rootPrim.Position) * invThisOrientation; + constrain = new BSConstraint6Dof( + m_physicsScene.World, rootPrim.PhysBody, liConstraint.member.PhysBody, midPoint, true, true ); - // relative rotation of the child to the parent - OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation; - OMV.Quaternion inverseChildRelativeRotation = OMV.Quaternion.Inverse(childRelativeRotation); + /* NOTE: below is an attempt to build constraint with full frame computation, etc. + * Using the midpoint is easier since it lets the Bullet code manipulate the transforms + * of the objects. + * Code left for future programmers. + // ================================================================================== + // relative position normalized to the root prim + OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation); + OMV.Vector3 childRelativePosition = (liConstraint.member.Position - rootPrim.Position) * invThisOrientation; - DetailLog("{0},BSLinksetConstraint.PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); - BS6DofConstraint constrain = new BS6DofConstraint( - PhysicsScene.World, rootPrim.Body, childPrim.Body, - OMV.Vector3.Zero, - OMV.Quaternion.Inverse(rootPrim.Orientation), - OMV.Vector3.Zero, - OMV.Quaternion.Inverse(childPrim.Orientation), - true, - true - ); - // ================================================================================== - */ + // relative rotation of the child to the parent + OMV.Quaternion childRelativeRotation = invThisOrientation * liConstraint.member.Orientation; + OMV.Quaternion inverseChildRelativeRotation = OMV.Quaternion.Inverse(childRelativeRotation); + + DetailLog("{0},BSLinksetConstraint.PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, liConstraint.member.LocalID); + constrain = new BS6DofConstraint( + PhysicsScene.World, rootPrim.Body, liConstraint.member.Body, + OMV.Vector3.Zero, + OMV.Quaternion.Inverse(rootPrim.Orientation), + OMV.Vector3.Zero, + OMV.Quaternion.Inverse(liConstraint.member.Orientation), + true, + true + ); + // ================================================================================== + */ + + break; + default: + break; + } + + liConstraint.SetConstraintParameters(constrain); m_physicsScene.Constraints.AddConstraint(constrain); - // zero linear and angular limits makes the objects unable to move in relation to each other - constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); - constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); - - // tweek the constraint to increase stability - constrain.UseFrameOffset(BSParam.LinkConstraintUseFrameOffset); - constrain.TranslationalLimitMotor(BSParam.LinkConstraintEnableTransMotor, - BSParam.LinkConstraintTransMotorMaxVel, - BSParam.LinkConstraintTransMotorMaxForce); - constrain.SetCFMAndERP(BSParam.LinkConstraintCFM, BSParam.LinkConstraintERP); - if (BSParam.LinkConstraintSolverIterations != 0f) - { - constrain.SetSolverIterations(BSParam.LinkConstraintSolverIterations); - } return constrain; } @@ -317,23 +387,24 @@ public sealed class BSLinksetConstraints : BSLinkset return; // Note the 'finally' clause at the botton which will get executed. } - foreach (BSPrimLinkable child in m_children) + ForEachLinkInfo((li) => { // A child in the linkset physically shows the mass of the whole linkset. // This allows Bullet to apply enough force on the child to move the whole linkset. // (Also do the mass stuff before recomputing the constraint so mass is not zero.) - child.UpdatePhysicalMassProperties(linksetMass, true); + li.member.UpdatePhysicalMassProperties(linksetMass, true); BSConstraint constrain; - if (!m_physicsScene.Constraints.TryGetConstraint(LinksetRoot.PhysBody, child.PhysBody, out constrain)) + if (!m_physicsScene.Constraints.TryGetConstraint(LinksetRoot.PhysBody, li.member.PhysBody, out constrain)) { // If constraint doesn't exist yet, create it. - constrain = BuildConstraint(LinksetRoot, child); + constrain = BuildConstraint(LinksetRoot, li); } constrain.RecomputeConstraintVariables(linksetMass); // PhysicsScene.PE.DumpConstraint(PhysicsScene.World, constrain.Constraint); // DEBUG DEBUG - } + return false; // 'false' says to keep processing other members + }); } finally { From 24df15dab7befd50f7a45eb54f001e6e481f0ec4 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Thu, 1 Aug 2013 17:43:06 -0700 Subject: [PATCH 06/33] BulletSim: add implementation of 'physSetLinksetType' and 'physGetLinksetType' and processing routines in BulletSim. Add linkset rebuild/conversion routine in BSLinkset. --- .../ExtendedPhysics/ExtendedPhysics.cs | 65 +++++++++++++++++-- .../Region/Physics/BulletSPlugin/BSLinkset.cs | 2 + .../BulletSPlugin/BSLinksetCompound.cs | 1 + .../BulletSPlugin/BSLinksetConstraints.cs | 1 + .../Region/Physics/BulletSPlugin/BSPrim.cs | 44 +++++++++++++ .../Physics/BulletSPlugin/BSPrimLinkable.cs | 30 +++++++++ .../Region/Physics/BulletSPlugin/BSScene.cs | 17 +++++ .../Region/Physics/Manager/PhysicsActor.cs | 3 +- .../Region/Physics/Manager/PhysicsScene.cs | 3 +- 9 files changed, 159 insertions(+), 7 deletions(-) diff --git a/OpenSim/Region/OptionalModules/Scripting/ExtendedPhysics/ExtendedPhysics.cs b/OpenSim/Region/OptionalModules/Scripting/ExtendedPhysics/ExtendedPhysics.cs index 0cbc5f9e76..d1d318c562 100755 --- a/OpenSim/Region/OptionalModules/Scripting/ExtendedPhysics/ExtendedPhysics.cs +++ b/OpenSim/Region/OptionalModules/Scripting/ExtendedPhysics/ExtendedPhysics.cs @@ -49,10 +49,20 @@ public class ExtendedPhysics : INonSharedRegionModule private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static string LogHeader = "[EXTENDED PHYSICS]"; + // ============================================================= // Since BulletSim is a plugin, this these values aren't defined easily in one place. - // This table must coorespond to an identical table in BSScene. + // This table must correspond to an identical table in BSScene. + + // Per scene functions. See BSScene. + + // Per avatar functions. See BSCharacter. + + // Per prim functions. See BSPrim. + public const string PhysFunctGetLinksetType = "BulletSim.GetLinksetType"; public const string PhysFunctSetLinksetType = "BulletSim.SetLinksetType"; + // ============================================================= + private IConfig Configuration { get; set; } private bool Enabled { get; set; } private Scene BaseScene { get; set; } @@ -123,6 +133,7 @@ public class ExtendedPhysics : INonSharedRegionModule // Register as LSL functions all the [ScriptInvocation] marked methods. Comms.RegisterScriptInvocations(this); + Comms.RegisterConstants(this); // When an object is modified, we might need to update its extended physics parameters BaseScene.EventManager.OnObjectAddedToScene += EventManager_OnObjectAddedToScene; @@ -136,7 +147,6 @@ public class ExtendedPhysics : INonSharedRegionModule private void EventManager_OnObjectAddedToScene(SceneObjectGroup obj) { - throw new NotImplementedException(); } // Event generated when some property of a prim changes. @@ -168,9 +178,11 @@ public class ExtendedPhysics : INonSharedRegionModule public static int PHYS_LINKSET_TYPE_MANUAL = 2; [ScriptInvocation] - public void physSetLinksetType(UUID hostID, UUID scriptID, int linksetType) + public int physSetLinksetType(UUID hostID, UUID scriptID, int linksetType) { - if (!Enabled) return; + int ret = -1; + + if (!Enabled) return ret; // The part that is requesting the change. SceneObjectPart requestingPart = BaseScene.GetSceneObjectPart(hostID); @@ -186,7 +198,7 @@ public class ExtendedPhysics : INonSharedRegionModule Physics.Manager.PhysicsActor rootPhysActor = rootPart.PhysActor; if (rootPhysActor != null) { - rootPhysActor.Extension(PhysFunctSetLinksetType, linksetType); + ret = (int)rootPhysActor.Extension(PhysFunctSetLinksetType, linksetType); } else { @@ -204,6 +216,49 @@ public class ExtendedPhysics : INonSharedRegionModule { m_log.WarnFormat("{0} physSetLinsetType: cannot find script object in scene. hostID={1}", LogHeader, hostID); } + return ret; + } + + [ScriptInvocation] + public int physGetLinksetType(UUID hostID, UUID scriptID) + { + int ret = -1; + + if (!Enabled) return ret; + + // The part that is requesting the change. + SceneObjectPart requestingPart = BaseScene.GetSceneObjectPart(hostID); + + if (requestingPart != null) + { + // The type is is always on the root of a linkset. + SceneObjectGroup containingGroup = requestingPart.ParentGroup; + SceneObjectPart rootPart = containingGroup.RootPart; + + if (rootPart != null) + { + Physics.Manager.PhysicsActor rootPhysActor = rootPart.PhysActor; + if (rootPhysActor != null) + { + ret = (int)rootPhysActor.Extension(PhysFunctGetLinksetType); + } + else + { + m_log.WarnFormat("{0} physGetLinksetType: root part does not have a physics actor. rootName={1}, hostID={2}", + LogHeader, rootPart.Name, hostID); + } + } + else + { + m_log.WarnFormat("{0} physGetLinksetType: root part does not exist. RequestingPartName={1}, hostID={2}", + LogHeader, requestingPart.Name, hostID); + } + } + else + { + m_log.WarnFormat("{0} physGetLinsetType: cannot find script object in scene. hostID={1}", LogHeader, hostID); + } + return ret; } } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 9613fe05e9..3afd52e142 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -79,6 +79,8 @@ public abstract class BSLinkset } } + public LinksetImplementation LinksetImpl { get; protected set; } + public BSPrimLinkable LinksetRoot { get; protected set; } protected BSScene m_physicsScene { get; private set; } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs index 53c35846b7..085d195d83 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs @@ -42,6 +42,7 @@ public sealed class BSLinksetCompound : BSLinkset public BSLinksetCompound(BSScene scene, BSPrimLinkable parent) : base(scene, parent) { + LinksetImpl = LinksetImplementation.Compound; } // ================================================================ diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs index d98bf77342..4bac222ab2 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs @@ -107,6 +107,7 @@ public sealed class BSLinksetConstraints : BSLinkset public BSLinksetConstraints(BSScene scene, BSPrimLinkable parent) : base(scene, parent) { + LinksetImpl = LinksetImplementation.Constraint; } // When physical properties are changed the linkset needs to recalculate diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index e92a1d2bc5..a0b6abc01f 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -1541,6 +1541,50 @@ public class BSPrim : BSPhysObject PhysicalActors.RemoveDependencies(); } + #region Extension + public override object Extension(string pFunct, params object[] pParams) + { + object ret = null; + switch (pFunct) + { + case BSScene.PhysFunctGetLinksetType: + { + BSPrimLinkable myHandle = this as BSPrimLinkable; + if (myHandle != null) + { + ret = (object)myHandle.LinksetType; + } + m_log.DebugFormat("{0} Extension.physGetLinksetType, type={1}", LogHeader, ret); + break; + } + case BSScene.PhysFunctSetLinksetType: + { + if (pParams.Length > 0) + { + BSLinkset.LinksetImplementation linksetType = (BSLinkset.LinksetImplementation)pParams[0]; + BSPrimLinkable myHandle = this as BSPrimLinkable; + if (myHandle != null && myHandle.Linkset.IsRoot(myHandle)) + { + PhysScene.TaintedObject("BSPrim.PhysFunctSetLinksetType", delegate() + { + // Cause the linkset type to change + m_log.DebugFormat("{0} Extension.physSetLinksetType, oldType={1}, newType={2}", + LogHeader, myHandle.Linkset.LinksetImpl, linksetType); + myHandle.ConvertLinkset(linksetType); + }); + } + ret = (object)(int)linksetType; + } + break; + } + default: + ret = base.Extension(pFunct, pParams); + break; + } + return ret; + } + #endregion // Extension + // The physics engine says that properties have updated. Update same and inform // the world that things have changed. // NOTE: BSPrim.UpdateProperties is overloaded by BSPrimLinkable which modifies updates from root and children prims. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs index 2f392da971..c565998086 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs @@ -233,5 +233,35 @@ public class BSPrimLinkable : BSPrimDisplaced base.HasSomeCollision = value; } } + + // Convert the existing linkset of this prim into a new type. + public bool ConvertLinkset(BSLinkset.LinksetImplementation newType) + { + bool ret = false; + if (LinksetType != newType) + { + BSLinkset oldLinkset = Linkset; + BSLinkset newLinkset = BSLinkset.Factory(PhysScene, this); + + // Pick up any physical dependencies this linkset might have in the physics engine. + oldLinkset.RemoveDependencies(this); + + // Copy the linkset children from the old linkset to the new (will be a new instance from the factory) + oldLinkset.ForEachLinkInfo((li) => + { + oldLinkset.RemoveMeFromLinkset(li.member); + newLinkset.AddMeToLinkset(li.member); + li.member.Linkset = newLinkset; + return false; + }); + + this.Linkset = newLinkset; + + // Force the shape and linkset to get reconstructed + newLinkset.Refresh(this); + this.ForceBodyShapeRebuild(true); + } + return ret; + } } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 41aca3b2a7..79ac5a5ba0 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -862,6 +862,23 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters public override bool IsThreaded { get { return false; } } + #region Extensions + // ============================================================= + // Per scene functions. See below. + + // Per avatar functions. See BSCharacter. + + // Per prim functions. See BSPrim. + public const string PhysFunctGetLinksetType = "BulletSim.GetLinksetType"; + public const string PhysFunctSetLinksetType = "BulletSim.SetLinksetType"; + // ============================================================= + + public override object Extension(string pFunct, params object[] pParams) + { + return base.Extension(pFunct, pParams); + } + #endregion // Extensions + #region Taints // The simulation execution order is: // Simulate() diff --git a/OpenSim/Region/Physics/Manager/PhysicsActor.cs b/OpenSim/Region/Physics/Manager/PhysicsActor.cs index 2500f27ede..1750853aeb 100644 --- a/OpenSim/Region/Physics/Manager/PhysicsActor.cs +++ b/OpenSim/Region/Physics/Manager/PhysicsActor.cs @@ -317,7 +317,8 @@ namespace OpenSim.Region.Physics.Manager // Extendable interface for new, physics engine specific operations public virtual object Extension(string pFunct, params object[] pParams) { - throw new NotImplementedException(); + // A NOP of the physics engine does not implement this feature + return null; } } diff --git a/OpenSim/Region/Physics/Manager/PhysicsScene.cs b/OpenSim/Region/Physics/Manager/PhysicsScene.cs index 07a1d36f6f..c93206d09d 100644 --- a/OpenSim/Region/Physics/Manager/PhysicsScene.cs +++ b/OpenSim/Region/Physics/Manager/PhysicsScene.cs @@ -338,7 +338,8 @@ namespace OpenSim.Region.Physics.Manager // Extendable interface for new, physics engine specific operations public virtual object Extension(string pFunct, params object[] pParams) { - throw new NotImplementedException(); + // A NOP if the extension thing is not implemented by the physics engine + return null; } } } From 5bdfd55ace4b673d8aaa3f25fd4bb675b1b28263 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 2 Aug 2013 10:32:43 -0700 Subject: [PATCH 07/33] BulletSim: When converting linkset types, don't try to change the list of linkset children while iterating through the list. --- .../Physics/BulletSPlugin/BSPrimLinkable.cs | 29 +++++++++++++------ 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs index c565998086..7179a6d571 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs @@ -240,26 +240,37 @@ public class BSPrimLinkable : BSPrimDisplaced bool ret = false; if (LinksetType != newType) { - BSLinkset oldLinkset = Linkset; + // Set the implementation type first so the call to BSLinkset.Factory gets the new type. + this.LinksetType = newType; + + BSLinkset oldLinkset = this.Linkset; BSLinkset newLinkset = BSLinkset.Factory(PhysScene, this); + this.Linkset = newLinkset; + // Pick up any physical dependencies this linkset might have in the physics engine. oldLinkset.RemoveDependencies(this); - // Copy the linkset children from the old linkset to the new (will be a new instance from the factory) - oldLinkset.ForEachLinkInfo((li) => + // Create a list of the children (mainly because can't interate through a list that's changing) + List children = new List(); + oldLinkset.ForEachMember((child) => { - oldLinkset.RemoveMeFromLinkset(li.member); - newLinkset.AddMeToLinkset(li.member); - li.member.Linkset = newLinkset; - return false; + if (!oldLinkset.IsRoot(child)) + children.Add(child); + return false; // 'false' says to continue to next member }); - this.Linkset = newLinkset; + // Remove the children from the old linkset and add to the new (will be a new instance from the factory) + foreach (BSPrimLinkable child in children) + { + oldLinkset.RemoveMeFromLinkset(child); + newLinkset.AddMeToLinkset(child); + child.Linkset = newLinkset; + } // Force the shape and linkset to get reconstructed newLinkset.Refresh(this); - this.ForceBodyShapeRebuild(true); + this.ForceBodyShapeRebuild(true /* inTaintTime */); } return ret; } From 54b1071556edf264835f990bb3595064d2b2e2f0 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 2 Aug 2013 23:12:54 +0100 Subject: [PATCH 08/33] Allow older teleport ConnectorProtocolVersion of "SIMULATION/0.1" to be manually forced in a new [SimulationService] config setting. This is for testing and debugging purposes to help determine whether a particular issue may be teleport related or not "SIMULATION/0.2" (the newer teleport protocol) remains the default. If the source simulator only implements "SIMULATION/0.1" this will correctly allow fallback to the older protocol. Specifying "SIMULATION/0.1" will force the older, less efficient protocol to always be used. --- .../Simulation/LocalSimulationConnector.cs | 33 +++++++++++-------- .../Simulation/RemoteSimulationConnector.cs | 21 +++++------- bin/config-include/Grid.ini | 11 +++++++ bin/config-include/Standalone.ini | 11 +++++++ 4 files changed, 49 insertions(+), 27 deletions(-) diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs index 697ce682c5..7aadb87b87 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs @@ -63,35 +63,40 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation /// private bool m_ModuleEnabled = false; - public LocalSimulationConnectorModule() - { - ServiceVersion = "SIMULATION/0.2"; - } - #region Region Module interface - public void Initialise(IConfigSource config) + public void Initialise(IConfigSource configSource) { - IConfig moduleConfig = config.Configs["Modules"]; + IConfig moduleConfig = configSource.Configs["Modules"]; if (moduleConfig != null) { string name = moduleConfig.GetString("SimulationServices", ""); if (name == Name) { - //IConfig userConfig = config.Configs["SimulationService"]; - //if (userConfig == null) - //{ - // m_log.Error("[AVATAR CONNECTOR]: SimulationService missing from OpenSim.ini"); - // return; - //} + InitialiseService(configSource); m_ModuleEnabled = true; - m_log.Info("[SIMULATION CONNECTOR]: Local simulation enabled"); + m_log.Info("[LOCAL SIMULATION CONNECTOR]: Local simulation enabled."); } } } + public void InitialiseService(IConfigSource configSource) + { + IConfig config = configSource.Configs["SimulationService"]; + if (config != null) + { + ServiceVersion = config.GetString("ConnectorProtocolVersion", "SIMULATION/0.2"); + + if (ServiceVersion != "SIMULATION/0.1" && ServiceVersion != "SIMULATION/0.2") + throw new Exception(string.Format("Invalid ConnectorProtocolVersion {0}", ServiceVersion)); + + m_log.InfoFormat( + "[LOCAL SIMULATION CONNECTOR]: Initialzied with connector protocol version {0}", ServiceVersion); + } + } + public void PostInitialise() { } diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs index 8722b80ced..f45f560a96 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs @@ -50,9 +50,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RemoteSimulationConnectorModule")] public class RemoteSimulationConnectorModule : ISharedRegionModule, ISimulationService { - private bool initialized = false; private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private bool initialized = false; protected bool m_enabled = false; protected Scene m_aScene; // RemoteSimulationConnector does not care about local regions; it delegates that to the Local module @@ -64,27 +64,23 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation #region Region Module interface - public virtual void Initialise(IConfigSource config) + public virtual void Initialise(IConfigSource configSource) { - - IConfig moduleConfig = config.Configs["Modules"]; + IConfig moduleConfig = configSource.Configs["Modules"]; if (moduleConfig != null) { string name = moduleConfig.GetString("SimulationServices", ""); if (name == Name) { - //IConfig userConfig = config.Configs["SimulationService"]; - //if (userConfig == null) - //{ - // m_log.Error("[AVATAR CONNECTOR]: SimulationService missing from OpenSim.ini"); - // return; - //} + m_localBackend = new LocalSimulationConnectorModule(); + + m_localBackend.InitialiseService(configSource); m_remoteConnector = new SimulationServiceConnector(); m_enabled = true; - m_log.Info("[SIMULATION CONNECTOR]: Remote simulation enabled"); + m_log.Info("[REMOTE SIMULATION CONNECTOR]: Remote simulation enabled."); } } } @@ -142,8 +138,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation } protected virtual void InitOnce(Scene scene) - { - m_localBackend = new LocalSimulationConnectorModule(); + { m_aScene = scene; //m_regionClient = new RegionToRegionClient(m_aScene, m_hyperlinkService); m_thisIP = Util.GetHostFromDNS(scene.RegionInfo.ExternalHostName); diff --git a/bin/config-include/Grid.ini b/bin/config-include/Grid.ini index 15ba55a27f..1837bdd752 100644 --- a/bin/config-include/Grid.ini +++ b/bin/config-include/Grid.ini @@ -30,6 +30,17 @@ SimulationServiceInConnector = true LibraryModule = true +[SimulationService] + ; This is the protocol version which the simulator advertises to the source destination when acting as a target destination for a teleport + ; It is used to control the teleport handoff process. + ; Valid values are + ; "SIMULATION/0.2" + ; - this is the default. A source simulator which only implements "SIMULATION/0.1" can still teleport with that protocol + ; - this protocol is more efficient than "SIMULATION/0.1" + ; "SIMULATION/0.1" + ; - this is an older teleport protocol used in OpenSimulator 0.7.5 and before. + ConnectorProtocolVersion = "SIMULATION/0.2" + [SimulationDataStore] LocalServiceModule = "OpenSim.Services.Connectors.dll:SimulationDataService" diff --git a/bin/config-include/Standalone.ini b/bin/config-include/Standalone.ini index d3b9cb4c85..7b7beb2cf0 100644 --- a/bin/config-include/Standalone.ini +++ b/bin/config-include/Standalone.ini @@ -26,6 +26,17 @@ GridInfoServiceInConnector = true MapImageServiceInConnector = true +[SimulationService] + ; This is the protocol version which the simulator advertises to the source destination when acting as a target destination for a teleport + ; It is used to control the teleport handoff process. + ; Valid values are + ; "SIMULATION/0.2" + ; - this is the default. A source simulator which only implements "SIMULATION/0.1" can still teleport with that protocol + ; - this protocol is more efficient than "SIMULATION/0.1" + ; "SIMULATION/0.1" + ; - this is an older teleport protocol used in OpenSimulator 0.7.5 and before. + ConnectorProtocolVersion = "SIMULATION/0.2" + [SimulationDataStore] LocalServiceModule = "OpenSim.Services.Connectors.dll:SimulationDataService" From 5198df3aa03eb47bc26b3c86924687612c015dce Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 2 Aug 2013 17:00:18 -0700 Subject: [PATCH 09/33] Issue: 10 simultaneous TPs, many not making it. Now bypassing the per-url lock -- we should be "ok" (or, more "ok") now that we have increased the connection limit on the http library. But this is a sensitive part of the code, so it may need reverting. --- OpenSim/Framework/WebUtil.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/OpenSim/Framework/WebUtil.cs b/OpenSim/Framework/WebUtil.cs index 6fb1e0c3c3..0e9de59376 100644 --- a/OpenSim/Framework/WebUtil.cs +++ b/OpenSim/Framework/WebUtil.cs @@ -145,10 +145,10 @@ namespace OpenSim.Framework public static OSDMap ServiceOSDRequest(string url, OSDMap data, string method, int timeout, bool compressed) { - lock (EndPointLock(url)) - { + //lock (EndPointLock(url)) + //{ return ServiceOSDRequestWorker(url,data,method,timeout,compressed); - } + //} } public static void LogOutgoingDetail(Stream outputStream) From 847c01f406359289097a6ad8d681002a4beff086 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 2 Aug 2013 17:38:08 -0700 Subject: [PATCH 10/33] Amend Justin's last commit regarding the new config var ServiceVersion. The section may not exist at all. --- .../Simulation/LocalSimulationConnector.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs index 7aadb87b87..e86d186759 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs @@ -84,10 +84,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation public void InitialiseService(IConfigSource configSource) { + ServiceVersion = "SIMULATION/0.2"; IConfig config = configSource.Configs["SimulationService"]; if (config != null) { - ServiceVersion = config.GetString("ConnectorProtocolVersion", "SIMULATION/0.2"); + ServiceVersion = config.GetString("ConnectorProtocolVersion", ServiceVersion); if (ServiceVersion != "SIMULATION/0.1" && ServiceVersion != "SIMULATION/0.2") throw new Exception(string.Format("Invalid ConnectorProtocolVersion {0}", ServiceVersion)); From b857353fc932bdf775abce2a3d34140cafe916ce Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sat, 3 Aug 2013 15:42:25 -0700 Subject: [PATCH 11/33] Making the J2KDecoderModule decoder function async. Could this be the cause of sim freeze? -- HandleRequestImage in LLClientView is now sync, which means that it cannot take too long to complete. However, its execution path may end up in J2KDecoderModule.Decode, which is heavy and could stop the packet processing thread while it's at it. --- .../Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs b/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs index 37646855ca..d9b0effaac 100644 --- a/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs +++ b/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs @@ -166,7 +166,7 @@ namespace OpenSim.Region.CoreModules.Agent.TextureSender // Do Decode! if (decode) - Decode(assetID, j2kData); + Util.FireAndForget(delegate { Decode(assetID, j2kData); }); } } From dcfeb95e98ca7b002170a5916f556f54f300678c Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sat, 3 Aug 2013 20:13:44 -0700 Subject: [PATCH 12/33] HG: If OutboundPermission is set to false, let's enforce stricter permissions by not allowing objects to be taken to inventory. --- .../HGInventoryAccessModule.cs | 31 +++++++++++++++++++ .../Framework/Scenes/Scene.Inventory.cs | 3 ++ 2 files changed, 34 insertions(+) diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs index 8f9800f681..978c2880a2 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs @@ -62,6 +62,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess private string m_ThisGatekeeper; private bool m_RestrictInventoryAccessAbroad; + private bool m_bypassPermissions = true; + // private bool m_Initialized = false; #region INonSharedRegionModule @@ -100,6 +102,10 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess } else m_log.Warn("[HG INVENTORY ACCESS MODULE]: HGInventoryAccessModule configs not found. ProfileServerURI not set!"); + + m_bypassPermissions = !Util.GetConfigVarFromSections(source, "serverside_object_permissions", + new string[] { "Startup", "Permissions" }, true); + } } } @@ -114,6 +120,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess scene.EventManager.OnNewInventoryItemUploadComplete += UploadInventoryItem; scene.EventManager.OnTeleportStart += TeleportStart; scene.EventManager.OnTeleportFail += TeleportFail; + + // We're fgoing to enforce some stricter permissions if Outbound is false + scene.Permissions.OnTakeObject += CanTakeObject; + scene.Permissions.OnTakeCopyObject += CanTakeObject; + } #endregion @@ -417,5 +428,25 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess } #endregion + + #region Permissions + + private bool CanTakeObject(UUID objectID, UUID stealer, Scene scene) + { + if (m_bypassPermissions) return true; + + if (!m_OutboundPermission && !UserManagementModule.IsLocalGridUser(stealer)) + { + SceneObjectGroup sog = null; + if (m_Scene.TryGetSceneObjectGroup(objectID, out sog) && sog.OwnerID == stealer) + return true; + + return false; + } + + return true; + } + + #endregion } } \ No newline at end of file diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 58fa18cd3e..2d1a3efe9f 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -2068,7 +2068,10 @@ namespace OpenSim.Region.Framework.Scenes { // If we don't have permission, stop right here if (!permissionToTakeCopy) + { + remoteClient.SendAlertMessage("You don't have permission to take the object"); return; + } permissionToTake = true; // Don't delete From 09cb2a37dd73296290c306f38412c1743b9eb820 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sat, 3 Aug 2013 20:36:30 -0700 Subject: [PATCH 13/33] More on HG inventory and OutboundPermission: disallowing giving inventory to foreigners if OutboundPermission is false --- .../InventoryAccess/HGInventoryAccessModule.cs | 13 ++++++++++++- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 3 +++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs index 978c2880a2..ce7ed26832 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs @@ -124,7 +124,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess // We're fgoing to enforce some stricter permissions if Outbound is false scene.Permissions.OnTakeObject += CanTakeObject; scene.Permissions.OnTakeCopyObject += CanTakeObject; - + scene.Permissions.OnTransferUserInventory += OnTransferUserInventory; } #endregion @@ -447,6 +447,17 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess return true; } + private bool OnTransferUserInventory(UUID itemID, UUID userID, UUID recipientID) + { + if (m_bypassPermissions) return true; + + if (!m_OutboundPermission && !UserManagementModule.IsLocalGridUser(recipientID)) + return false; + + return true; + } + + #endregion } } \ No newline at end of file diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 2d1a3efe9f..8e4e307f1f 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -556,6 +556,9 @@ namespace OpenSim.Region.Framework.Scenes { //Console.WriteLine("Scene.Inventory.cs: GiveInventoryItem"); + if (!Permissions.CanTransferUserInventory(itemId, senderId, recipient)) + return null; + InventoryItemBase item = new InventoryItemBase(itemId, senderId); item = InventoryService.GetItem(item); From 5b4b349776613d9054e85727f8f6a1f079a5225a Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sat, 3 Aug 2013 21:27:32 -0700 Subject: [PATCH 14/33] Fix the failing TestSendImage. J2K decoding is async. --- .../Linden/UDP/Tests/LLImageManagerTests.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs index 83144e3bcd..6aa8bcc58a 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs @@ -29,6 +29,7 @@ using System; using System.IO; using System.Net; using System.Reflection; +using System.Threading; using log4net.Config; using Nini.Config; using NUnit.Framework; @@ -105,7 +106,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests args.requestSequence = 1; llim.EnqueueReq(args); - llim.ProcessImageQueue(20); + + // We now have to wait and hit the processing wheel, because the decoding is async + int i = 10; + while (i-- > 0) + { + llim.ProcessImageQueue(20); + Thread.Sleep(100); + } Assert.That(tc.SentImageDataPackets.Count, Is.EqualTo(1)); } From 05012bb0df9b109f792b83e82779d3f69fb37ecb Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Mon, 5 Aug 2013 08:09:30 -0700 Subject: [PATCH 15/33] Group notices bug fix: use a new IM for each member of the group, otherwise the fields get messed up because the transfer is async --- OpenSim/Addons/Groups/GroupsModule.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs index da8030c22b..830c6714c8 100644 --- a/OpenSim/Addons/Groups/GroupsModule.cs +++ b/OpenSim/Addons/Groups/GroupsModule.cs @@ -467,12 +467,12 @@ namespace OpenSim.Groups } // Send notice out to everyone that wants notices - // Build notice IIM - GridInstantMessage msg = CreateGroupNoticeIM(UUID.Zero, NoticeID, (byte)OpenMetaverse.InstantMessageDialog.GroupNotice); foreach (GroupMembersData member in m_groupData.GetGroupMembers(GetRequestingAgentIDStr(remoteClient), GroupID)) { if (member.AcceptNotices) { + // Build notice IIM, one of reach, because the sending may be async + GridInstantMessage msg = CreateGroupNoticeIM(UUID.Zero, NoticeID, (byte)OpenMetaverse.InstantMessageDialog.GroupNotice); msg.toAgentID = member.AgentID.Guid; OutgoingInstantMessage(msg, member.AgentID); } From 76bd3de2fd243d0c910404af8a9998de746b04c4 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Mon, 5 Aug 2013 19:22:47 +0100 Subject: [PATCH 16/33] Add checks monitoring framework to provide alerts if certain conditions do not hold. Not yet in use. --- OpenSim/Framework/Monitoring/Checks/Check.cs | 118 ++++++++ OpenSim/Framework/Monitoring/ChecksManager.cs | 262 ++++++++++++++++++ OpenSim/Framework/Monitoring/StatsManager.cs | 6 +- OpenSim/Framework/Monitoring/Watchdog.cs | 1 + OpenSim/Framework/Servers/ServerBase.cs | 1 + 5 files changed, 385 insertions(+), 3 deletions(-) create mode 100644 OpenSim/Framework/Monitoring/Checks/Check.cs create mode 100644 OpenSim/Framework/Monitoring/ChecksManager.cs diff --git a/OpenSim/Framework/Monitoring/Checks/Check.cs b/OpenSim/Framework/Monitoring/Checks/Check.cs new file mode 100644 index 0000000000..594386a93f --- /dev/null +++ b/OpenSim/Framework/Monitoring/Checks/Check.cs @@ -0,0 +1,118 @@ +/* + * 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.Text; + +namespace OpenSim.Framework.Monitoring +{ + public class Check + { +// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + public static readonly char[] DisallowedShortNameCharacters = { '.' }; + + /// + /// Category of this stat (e.g. cache, scene, etc). + /// + public string Category { get; private set; } + + /// + /// Containing name for this stat. + /// FIXME: In the case of a scene, this is currently the scene name (though this leaves + /// us with a to-be-resolved problem of non-unique region names). + /// + /// + /// The container. + /// + public string Container { get; private set; } + + /// + /// Action used to check whether alert should go off. + /// + /// + /// Should return true if check passes. False otherwise. + /// + public Func CheckFunc { get; private set; } + + /// + /// Message from the last failure, if any. If there is no message or no failure then will be null. + /// + /// + /// Should be set by the CheckFunc when applicable. + /// + public string LastFailureMessage { get; set; } + + public StatVerbosity Verbosity { get; private set; } + public string ShortName { get; private set; } + public string Name { get; private set; } + public string Description { get; private set; } + + public Check( + string shortName, + string name, + string description, + string category, + string container, + Func checkFunc, + StatVerbosity verbosity) + { + if (ChecksManager.SubCommands.Contains(category)) + throw new Exception( + string.Format("Alert cannot be in category '{0}' since this is reserved for a subcommand", category)); + + foreach (char c in DisallowedShortNameCharacters) + { + if (shortName.IndexOf(c) != -1) + throw new Exception(string.Format("Alert name {0} cannot contain character {1}", shortName, c)); + } + + ShortName = shortName; + Name = name; + Description = description; + Category = category; + Container = container; + CheckFunc = checkFunc; + Verbosity = verbosity; + } + + public bool CheckIt() + { + return CheckFunc(this); + } + + public virtual string ToConsoleString() + { + return string.Format( + "{0}.{1}.{2} - {3}", + Category, + Container, + ShortName, + Description); + } + } +} \ No newline at end of file diff --git a/OpenSim/Framework/Monitoring/ChecksManager.cs b/OpenSim/Framework/Monitoring/ChecksManager.cs new file mode 100644 index 0000000000..e4a7f8ca2f --- /dev/null +++ b/OpenSim/Framework/Monitoring/ChecksManager.cs @@ -0,0 +1,262 @@ +/* + * 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.Text; +using log4net; + +namespace OpenSim.Framework.Monitoring +{ + /// + /// Static class used to register/deregister checks on runtime conditions. + /// + public static class ChecksManager + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + // Subcommand used to list other stats. + public const string ListSubCommand = "list"; + + // All subcommands + public static HashSet SubCommands = new HashSet { ListSubCommand }; + + /// + /// Checks categorized by category/container/shortname + /// + /// + /// Do not add or remove directly from this dictionary. + /// + public static SortedDictionary>> RegisteredChecks + = new SortedDictionary>>(); + + public static void RegisterConsoleCommands(ICommandConsole console) + { + console.Commands.AddCommand( + "General", + false, + "show checks", + "show checks", + "Show checks configured for this server", + "If no argument is specified then info on all checks will be shown.\n" + + "'list' argument will show check categories.\n" + + "THIS FACILITY IS EXPERIMENTAL", + HandleShowchecksCommand); + } + + public static void HandleShowchecksCommand(string module, string[] cmd) + { + ICommandConsole con = MainConsole.Instance; + + if (cmd.Length > 2) + { + foreach (string name in cmd.Skip(2)) + { + string[] components = name.Split('.'); + + string categoryName = components[0]; +// string containerName = components.Length > 1 ? components[1] : null; + + if (categoryName == ListSubCommand) + { + con.Output("check categories available are:"); + + foreach (string category in RegisteredChecks.Keys) + con.OutputFormat(" {0}", category); + } +// else +// { +// SortedDictionary> category; +// if (!Registeredchecks.TryGetValue(categoryName, out category)) +// { +// con.OutputFormat("No such category as {0}", categoryName); +// } +// else +// { +// if (String.IsNullOrEmpty(containerName)) +// { +// OutputConfiguredToConsole(con, category); +// } +// else +// { +// SortedDictionary container; +// if (category.TryGetValue(containerName, out container)) +// { +// OutputContainerChecksToConsole(con, container); +// } +// else +// { +// con.OutputFormat("No such container {0} in category {1}", containerName, categoryName); +// } +// } +// } +// } + } + } + else + { + OutputAllChecksToConsole(con); + } + } + + /// + /// Registers a statistic. + /// + /// + /// + public static bool RegisterCheck(Check check) + { + SortedDictionary> category = null, newCategory; + SortedDictionary container = null, newContainer; + + lock (RegisteredChecks) + { + // Check name is not unique across category/container/shortname key. + // XXX: For now just return false. This is to avoid problems in regression tests where all tests + // in a class are run in the same instance of the VM. + if (TryGetCheckParents(check, out category, out container)) + return false; + + // We take a copy-on-write approach here of replacing dictionaries when keys are added or removed. + // This means that we don't need to lock or copy them on iteration, which will be a much more + // common operation after startup. + if (container != null) + newContainer = new SortedDictionary(container); + else + newContainer = new SortedDictionary(); + + if (category != null) + newCategory = new SortedDictionary>(category); + else + newCategory = new SortedDictionary>(); + + newContainer[check.ShortName] = check; + newCategory[check.Container] = newContainer; + RegisteredChecks[check.Category] = newCategory; + } + + return true; + } + + /// + /// Deregister an check + /// > + /// + /// + public static bool DeregisterCheck(Check check) + { + SortedDictionary> category = null, newCategory; + SortedDictionary container = null, newContainer; + + lock (RegisteredChecks) + { + if (!TryGetCheckParents(check, out category, out container)) + return false; + + newContainer = new SortedDictionary(container); + newContainer.Remove(check.ShortName); + + newCategory = new SortedDictionary>(category); + newCategory.Remove(check.Container); + + newCategory[check.Container] = newContainer; + RegisteredChecks[check.Category] = newCategory; + + return true; + } + } + + public static bool TryGetCheckParents( + Check check, + out SortedDictionary> category, + out SortedDictionary container) + { + category = null; + container = null; + + lock (RegisteredChecks) + { + if (RegisteredChecks.TryGetValue(check.Category, out category)) + { + if (category.TryGetValue(check.Container, out container)) + { + if (container.ContainsKey(check.ShortName)) + return true; + } + } + } + + return false; + } + + public static void CheckChecks() + { + lock (RegisteredChecks) + { + foreach (SortedDictionary> category in RegisteredChecks.Values) + { + foreach (SortedDictionary container in category.Values) + { + foreach (Check check in container.Values) + { + if (!check.CheckIt()) + m_log.WarnFormat( + "[CHECKS MANAGER]: Check {0}.{1}.{2} failed with message {3}", check.Category, check.Container, check.ShortName, check.LastFailureMessage); + } + } + } + } + } + + private static void OutputAllChecksToConsole(ICommandConsole con) + { + foreach (var category in RegisteredChecks.Values) + { + OutputCategoryChecksToConsole(con, category); + } + } + + private static void OutputCategoryChecksToConsole( + ICommandConsole con, SortedDictionary> category) + { + foreach (var container in category.Values) + { + OutputContainerChecksToConsole(con, container); + } + } + + private static void OutputContainerChecksToConsole(ICommandConsole con, SortedDictionary container) + { + foreach (Check check in container.Values) + { + con.Output(check.ToConsoleString()); + } + } + } +} \ No newline at end of file diff --git a/OpenSim/Framework/Monitoring/StatsManager.cs b/OpenSim/Framework/Monitoring/StatsManager.cs index e6a230454c..87197f422f 100644 --- a/OpenSim/Framework/Monitoring/StatsManager.cs +++ b/OpenSim/Framework/Monitoring/StatsManager.cs @@ -35,9 +35,9 @@ using OpenMetaverse.StructuredData; namespace OpenSim.Framework.Monitoring { /// - /// Singleton used to provide access to statistics reporters + /// Static class used to register/deregister/fetch statistics /// - public class StatsManager + public static class StatsManager { // Subcommand used to list other stats. public const string AllSubCommand = "all"; @@ -257,7 +257,7 @@ namespace OpenSim.Framework.Monitoring // } /// - /// Registers a statistic. + /// Register a statistic. /// /// /// diff --git a/OpenSim/Framework/Monitoring/Watchdog.cs b/OpenSim/Framework/Monitoring/Watchdog.cs index 3f992b1e3b..45762a67c9 100644 --- a/OpenSim/Framework/Monitoring/Watchdog.cs +++ b/OpenSim/Framework/Monitoring/Watchdog.cs @@ -380,6 +380,7 @@ namespace OpenSim.Framework.Monitoring if (MemoryWatchdog.Enabled) MemoryWatchdog.Update(); + ChecksManager.CheckChecks(); StatsManager.RecordStats(); m_watchdogTimer.Start(); diff --git a/OpenSim/Framework/Servers/ServerBase.cs b/OpenSim/Framework/Servers/ServerBase.cs index 029b848946..a8e0f81d3f 100644 --- a/OpenSim/Framework/Servers/ServerBase.cs +++ b/OpenSim/Framework/Servers/ServerBase.cs @@ -272,6 +272,7 @@ namespace OpenSim.Framework.Servers "shutdown", "Quit the application", (mod, args) => Shutdown()); + ChecksManager.RegisterConsoleCommands(m_console); StatsManager.RegisterConsoleCommands(m_console); } From 03698121ed1e605a126f9bba37088f145a0ef2fb Mon Sep 17 00:00:00 2001 From: Mic Bowman Date: Mon, 5 Aug 2013 12:34:53 -0700 Subject: [PATCH 17/33] Remove some debugging from simian connectors. --- .../Connectors/SimianGrid/SimianExternalCapsModule.cs | 6 +++++- OpenSim/Services/Connectors/SimianGrid/SimianGrid.cs | 8 ++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianExternalCapsModule.cs b/OpenSim/Services/Connectors/SimianGrid/SimianExternalCapsModule.cs index 8226705183..e85b0b7e72 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianExternalCapsModule.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianExternalCapsModule.cs @@ -79,7 +79,11 @@ namespace OpenSim.Services.Connectors.SimianGrid { m_simianURL = m_config.GetString("SimianServiceURL"); if (String.IsNullOrEmpty(m_simianURL)) - m_log.ErrorFormat("[SimianGrid] service URL is not defined"); + { + //m_log.DebugFormat("[SimianGrid] service URL is not defined"); + m_enabled = false; + return; + } } } else diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianGrid.cs b/OpenSim/Services/Connectors/SimianGrid/SimianGrid.cs index a4dd36c40e..e7d2f86db6 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianGrid.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianGrid.cs @@ -74,11 +74,15 @@ namespace OpenSim.Services.Connectors.SimianGrid { m_simianURL = m_config.GetString("SimianServiceURL"); if (String.IsNullOrEmpty(m_simianURL)) - m_log.ErrorFormat("[SimianGrid] service URL is not defined"); + { + // m_log.DebugFormat("[SimianGrid] service URL is not defined"); + m_enabled = false; + return; + } InitialiseSimCap(); SimulatorCapability = SimulatorCapability.Trim(); - m_log.WarnFormat("[SimianExternalCaps] using {0} as simulator capability",SimulatorCapability); + m_log.InfoFormat("[SimianExternalCaps] using {0} as simulator capability",SimulatorCapability); } } catch (Exception e) From 7f0d9ad64473ad0defb8d534a8ddadc6d471e4a5 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Mon, 5 Aug 2013 20:36:46 +0100 Subject: [PATCH 18/33] Make test AssetsClient print out more information about any failure to set thread numbers and immediate post config thread numbers --- OpenSim/Tests/Clients/Assets/AssetsClient.cs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/OpenSim/Tests/Clients/Assets/AssetsClient.cs b/OpenSim/Tests/Clients/Assets/AssetsClient.cs index 26d740b771..e988d0e36a 100644 --- a/OpenSim/Tests/Clients/Assets/AssetsClient.cs +++ b/OpenSim/Tests/Clients/Assets/AssetsClient.cs @@ -68,8 +68,18 @@ namespace OpenSim.Tests.Clients.AssetsClient m_log.InfoFormat("[ASSET CLIENT]: Connecting to {0} max threads = {1} - {2}", serverURI, max1, max2); ThreadPool.GetMinThreads(out max1, out max2); m_log.InfoFormat("[ASSET CLIENT]: Connecting to {0} min threads = {1} - {2}", serverURI, max1, max2); - ThreadPool.SetMinThreads(1, 1); - ThreadPool.SetMaxThreads(10, 3); + + if (!ThreadPool.SetMinThreads(1, 1)) + m_log.WarnFormat("[ASSET CLIENT]: Failed to set min threads"); + + if (!ThreadPool.SetMaxThreads(10, 3)) + m_log.WarnFormat("[ASSET CLIENT]: Failed to set max threads"); + + ThreadPool.GetMaxThreads(out max1, out max2); + m_log.InfoFormat("[ASSET CLIENT]: Post set max threads = {1} - {2}", serverURI, max1, max2); + ThreadPool.GetMinThreads(out max1, out max2); + m_log.InfoFormat("[ASSET CLIENT]: Post set min threads = {1} - {2}", serverURI, max1, max2); + ServicePointManager.DefaultConnectionLimit = 12; AssetServicesConnector m_Connector = new AssetServicesConnector(serverURI); From b8612e005a2f85da2bde2d555f910934cccb218a Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Mon, 5 Aug 2013 20:47:47 +0100 Subject: [PATCH 19/33] At OpenSimulator startup, print out default min built-in threadpool threads as well as max. Make it clear that we only try to adjust max, and log at warn level if this fails. Other minor logging cleanup. --- OpenSim/Region/Application/Application.cs | 41 +++++++++++++++-------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/OpenSim/Region/Application/Application.cs b/OpenSim/Region/Application/Application.cs index e451aa8148..2e155ec9dc 100644 --- a/OpenSim/Region/Application/Application.cs +++ b/OpenSim/Region/Application/Application.cs @@ -103,26 +103,38 @@ namespace OpenSim "[OPENSIM MAIN]: Environment variable MONO_THREADS_PER_CPU is {0}", monoThreadsPerCpu ?? "unset"); // Verify the Threadpool allocates or uses enough worker and IO completion threads - // .NET 2.0 workerthreads default to 50 * numcores - // .NET 3.0 workerthreads defaults to 250 * numcores - // .NET 4.0 workerthreads are dynamic based on bitness and OS resources - // Max IO Completion threads are 1000 on all 3 CLRs. + // .NET 2.0, workerthreads default to 50 * numcores + // .NET 3.0, workerthreads defaults to 250 * numcores + // .NET 4.0, workerthreads are dynamic based on bitness and OS resources + // Max IO Completion threads are 1000 on all 3 CLRs + // + // Mono 2.10.9 to at least Mono 3.1, workerthreads default to 100 * numcores, iocp threads to 4 * numcores int workerThreadsMin = 500; int workerThreadsMax = 1000; // may need further adjustment to match other CLR int iocpThreadsMin = 1000; int iocpThreadsMax = 2000; // may need further adjustment to match other CLR + + { + int currentMinWorkerThreads, currentMinIocpThreads; + System.Threading.ThreadPool.GetMinThreads(out currentMinWorkerThreads, out currentMinIocpThreads); + m_log.InfoFormat( + "[OPENSIM MAIN]: Runtime gave us {0} min worker threads and {1} min IOCP threads", + currentMinWorkerThreads, currentMinIocpThreads); + } + int workerThreads, iocpThreads; System.Threading.ThreadPool.GetMaxThreads(out workerThreads, out iocpThreads); - m_log.InfoFormat("[OPENSIM MAIN]: Runtime gave us {0} worker threads and {1} IOCP threads", workerThreads, iocpThreads); + m_log.InfoFormat("[OPENSIM MAIN]: Runtime gave us {0} max worker threads and {1} max IOCP threads", workerThreads, iocpThreads); + if (workerThreads < workerThreadsMin) { workerThreads = workerThreadsMin; - m_log.InfoFormat("[OPENSIM MAIN]: Bumping up to worker threads to {0}",workerThreads); + m_log.InfoFormat("[OPENSIM MAIN]: Bumping up to max worker threads to {0}",workerThreads); } if (workerThreads > workerThreadsMax) { workerThreads = workerThreadsMax; - m_log.InfoFormat("[OPENSIM MAIN]: Limiting worker threads to {0}",workerThreads); + m_log.InfoFormat("[OPENSIM MAIN]: Limiting max worker threads to {0}",workerThreads); } // Increase the number of IOCP threads available. @@ -130,22 +142,24 @@ namespace OpenSim if (iocpThreads < iocpThreadsMin) { iocpThreads = iocpThreadsMin; - m_log.InfoFormat("[OPENSIM MAIN]: Bumping up IO completion threads to {0}",iocpThreads); + m_log.InfoFormat("[OPENSIM MAIN]: Bumping up max IO completion threads to {0}",iocpThreads); } // Make sure we don't overallocate IOCP threads and thrash system resources if ( iocpThreads > iocpThreadsMax ) { iocpThreads = iocpThreadsMax; - m_log.InfoFormat("[OPENSIM MAIN]: Limiting IO completion threads to {0}",iocpThreads); + m_log.InfoFormat("[OPENSIM MAIN]: Limiting max IO completion threads to {0}",iocpThreads); } // set the resulting worker and IO completion thread counts back to ThreadPool if ( System.Threading.ThreadPool.SetMaxThreads(workerThreads, iocpThreads) ) { - m_log.InfoFormat("[OPENSIM MAIN]: Threadpool set to {0} worker threads and {1} IO completion threads", workerThreads, iocpThreads); + m_log.InfoFormat( + "[OPENSIM MAIN]: Threadpool set to {0} max worker threads and {1} max IO completion threads", + workerThreads, iocpThreads); } else { - m_log.Info("[OPENSIM MAIN]: Threadpool reconfiguration failed, runtime defaults still in effect."); + m_log.Warn("[OPENSIM MAIN]: Threadpool reconfiguration failed, runtime defaults still in effect."); } // Check if the system is compatible with OpenSimulator. @@ -153,17 +167,16 @@ namespace OpenSim string supported = String.Empty; if (Util.IsEnvironmentSupported(ref supported)) { - m_log.Info("Environment is compatible.\n"); + m_log.Info("[OPENSIM MAIN]: Environment is supported by OpenSimulator."); } else { - m_log.Warn("Environment is unsupported (" + supported + ")\n"); + m_log.Warn("[OPENSIM MAIN]: Environment is not supported by OpenSimulator (" + supported + ")\n"); } // Configure nIni aliases and localles Culture.SetCurrentCulture(); - // Validate that the user has the most basic configuration done // If not, offer to do the most basic configuration for them warning them along the way of the importance of // reading these files. From 24dcf3cf6a95596ce0ac188a63bb5c2c4c47dcee Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Mon, 5 Aug 2013 20:51:40 +0100 Subject: [PATCH 20/33] Comment out debug log lines about script modules comms for now. If this is an issue, could change log4net config instead to allow re-enablement --- .../Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs b/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs index 6bf50d2504..a515346260 100644 --- a/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs @@ -163,7 +163,7 @@ namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms public void RegisterScriptInvocation(object target, MethodInfo mi) { - m_log.DebugFormat("[MODULE COMMANDS] Register method {0} from type {1}", mi.Name, (target is Type) ? ((Type)target).Name : target.GetType().Name); +// m_log.DebugFormat("[MODULE COMMANDS] Register method {0} from type {1}", mi.Name, (target is Type) ? ((Type)target).Name : target.GetType().Name); Type delegateType; List typeArgs = mi.GetParameters() @@ -323,7 +323,7 @@ namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms /// public void RegisterConstant(string cname, object value) { - m_log.DebugFormat("[MODULE COMMANDS] register constant <{0}> with value {1}",cname,value.ToString()); +// m_log.DebugFormat("[MODULE COMMANDS] register constant <{0}> with value {1}",cname,value.ToString()); lock (m_constants) { m_constants.Add(cname,value); From 946b37096698c818104405cb511579e810a62973 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Mon, 5 Aug 2013 14:21:17 -0700 Subject: [PATCH 21/33] Child agent updates: remove the dependency on the root agent's camera position. That was a complete overkill that is unnecessary at this point. --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 456c8cc4af..0ba2dabe5e 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -2989,8 +2989,7 @@ namespace OpenSim.Region.Framework.Scenes } // Minimum Draw distance is 64 meters, the Radius of the draw distance sphere is 32m - if (Util.GetDistanceTo(AbsolutePosition, m_lastChildAgentUpdatePosition) >= Scene.ChildReprioritizationDistance || - Util.GetDistanceTo(CameraPosition, m_lastChildAgentUpdateCamPosition) >= Scene.ChildReprioritizationDistance) + if (Util.GetDistanceTo(AbsolutePosition, m_lastChildAgentUpdatePosition) >= Scene.ChildReprioritizationDistance) { m_lastChildAgentUpdatePosition = AbsolutePosition; m_lastChildAgentUpdateCamPosition = CameraPosition; From 160659f68382187d7e949ca11c2942907671fe86 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Mon, 5 Aug 2013 23:04:36 +0100 Subject: [PATCH 22/33] Make it possible to set worker/iocp min/max threadpool limits on the fly with the console command "debug threadpool set" --- OpenSim/Framework/Servers/ServerBase.cs | 78 +++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/OpenSim/Framework/Servers/ServerBase.cs b/OpenSim/Framework/Servers/ServerBase.cs index a8e0f81d3f..55b6c58dd5 100644 --- a/OpenSim/Framework/Servers/ServerBase.cs +++ b/OpenSim/Framework/Servers/ServerBase.cs @@ -256,6 +256,12 @@ namespace OpenSim.Framework.Servers "Show thread status. Synonym for \"show threads\"", (string module, string[] args) => Notice(GetThreadsReport())); + m_console.Commands.AddCommand ( + "Debug", false, "debug threadpool set", + "debug threadpool set worker|iocp min|max ", + "Set threadpool parameters. For debug purposes.", + HandleDebugThreadpoolSet); + m_console.Commands.AddCommand( "General", false, "force gc", "force gc", @@ -283,6 +289,78 @@ namespace OpenSim.Framework.Servers m_serverStatsCollector.Start(); } + private void HandleDebugThreadpoolSet(string module, string[] args) + { + if (args.Length != 6) + { + Notice("Usage: debug threadpool set worker|iocp min|max "); + return; + } + + int newThreads; + + if (!ConsoleUtil.TryParseConsoleInt(m_console, args[5], out newThreads)) + return; + + string poolType = args[3]; + string bound = args[4]; + + bool fail = false; + int workerThreads, iocpThreads; + + if (poolType == "worker") + { + if (bound == "min") + { + ThreadPool.GetMinThreads(out workerThreads, out iocpThreads); + + if (!ThreadPool.SetMinThreads(newThreads, iocpThreads)) + fail = true; + } + else + { + ThreadPool.GetMaxThreads(out workerThreads, out iocpThreads); + + if (!ThreadPool.SetMaxThreads(newThreads, iocpThreads)) + fail = true; + } + } + else + { + if (bound == "min") + { + ThreadPool.GetMinThreads(out workerThreads, out iocpThreads); + + if (!ThreadPool.SetMinThreads(workerThreads, newThreads)) + fail = true; + } + else + { + ThreadPool.GetMaxThreads(out workerThreads, out iocpThreads); + + if (!ThreadPool.SetMaxThreads(workerThreads, newThreads)) + fail = true; + } + } + + if (fail) + { + Notice("ERROR: Could not set {0} {1} threads to {2}", poolType, bound, newThreads); + } + else + { + int minWorkerThreads, maxWorkerThreads, minIocpThreads, maxIocpThreads; + + ThreadPool.GetMinThreads(out minWorkerThreads, out minIocpThreads); + ThreadPool.GetMaxThreads(out maxWorkerThreads, out maxIocpThreads); + + Notice("Min worker threads now {0}", minWorkerThreads); + Notice("Min IOCP threads now {0}", minIocpThreads); + Notice("Max worker threads now {0}", maxWorkerThreads); + Notice("Max IOCP threads now {0}", maxIocpThreads); + } + } + private void HandleForceGc(string module, string[] args) { Notice("Manually invoking runtime garbage collection"); From 139dcf1246b933f76bf72d2306f3f70d2ca61479 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Mon, 5 Aug 2013 23:06:17 +0100 Subject: [PATCH 23/33] minor: move "threads abort" and "force gc" console commands into debug category - these are not things one needs to do in normal operation --- OpenSim/Framework/Servers/ServerBase.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Framework/Servers/ServerBase.cs b/OpenSim/Framework/Servers/ServerBase.cs index 55b6c58dd5..0545bea015 100644 --- a/OpenSim/Framework/Servers/ServerBase.cs +++ b/OpenSim/Framework/Servers/ServerBase.cs @@ -246,7 +246,7 @@ namespace OpenSim.Framework.Servers "Show thread status", HandleShow); m_console.Commands.AddCommand( - "General", false, "threads abort", + "Debug", false, "threads abort", "threads abort ", "Abort a managed thread. Use \"show threads\" to find possible threads.", HandleThreadsAbort); @@ -263,7 +263,7 @@ namespace OpenSim.Framework.Servers HandleDebugThreadpoolSet); m_console.Commands.AddCommand( - "General", false, "force gc", + "Debug", false, "force gc", "force gc", "Manually invoke runtime garbage collection. For debugging purposes", HandleForceGc); From f9dc5815c4788aefed7eab01fa79709d3921e22a Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Mon, 5 Aug 2013 23:15:30 +0100 Subject: [PATCH 24/33] For LLImageManagerTests, make tests execute under synchronous fire and forget conditions. I generally prefer this approach for regression tests because of the complexity of accounting for different threading conditions. --- .../Linden/UDP/Tests/LLImageManagerTests.cs | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs index 6aa8bcc58a..575e54c685 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs @@ -54,6 +54,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests [TestFixtureSetUp] public void FixtureInit() { + // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread. + Util.FireAndForgetMethod = FireAndForgetMethod.None; + using ( Stream resource = GetType().Assembly.GetManifestResourceStream( @@ -73,6 +76,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests } } + [TestFixtureTearDown] + public void TearDown() + { + // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple + // threads. Possibly, later tests should be rewritten not to worry about such things. + Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod; + } + [SetUp] public override void SetUp() { @@ -106,14 +117,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests args.requestSequence = 1; llim.EnqueueReq(args); - - // We now have to wait and hit the processing wheel, because the decoding is async - int i = 10; - while (i-- > 0) - { - llim.ProcessImageQueue(20); - Thread.Sleep(100); - } + llim.ProcessImageQueue(20); Assert.That(tc.SentImageDataPackets.Count, Is.EqualTo(1)); } From 9bcf07279513294d58c3076e7d8a6eb5ee64c759 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Mon, 5 Aug 2013 23:44:48 +0100 Subject: [PATCH 25/33] Make it possible to switch whether we serialize osd requests per endpoint or not, either via config (SerializeOSDRequests in [Network]) or via the "debug comms set" console command. For debug purposes to assess what impact this has on network response in a heavy test environment. --- OpenSim/Framework/Console/ConsoleUtil.cs | 22 +++++++++++++- OpenSim/Framework/Servers/ServerBase.cs | 37 ++++++++++++++++++++++++ OpenSim/Framework/WebUtil.cs | 20 ++++++++++--- 3 files changed, 74 insertions(+), 5 deletions(-) diff --git a/OpenSim/Framework/Console/ConsoleUtil.cs b/OpenSim/Framework/Console/ConsoleUtil.cs index 97a86a8099..c0ff454831 100644 --- a/OpenSim/Framework/Console/ConsoleUtil.cs +++ b/OpenSim/Framework/Console/ConsoleUtil.cs @@ -156,7 +156,27 @@ namespace OpenSim.Framework.Console } /// - /// Convert a minimum vector input from the console to an OpenMetaverse.Vector3 + /// Convert a console integer to an int, automatically complaining if a console is given. + /// + /// Can be null if no console is available. + /// /param> + /// + /// + public static bool TryParseConsoleBool(ICommandConsole console, string rawConsoleString, out bool b) + { + if (!bool.TryParse(rawConsoleString, out b)) + { + if (console != null) + console.OutputFormat("ERROR: {0} is not a true or false value", rawConsoleString); + + return false; + } + + return true; + } + + /// + /// Convert a console integer to an int, automatically complaining if a console is given. /// /// Can be null if no console is available. /// /param> diff --git a/OpenSim/Framework/Servers/ServerBase.cs b/OpenSim/Framework/Servers/ServerBase.cs index 0545bea015..824c7e2431 100644 --- a/OpenSim/Framework/Servers/ServerBase.cs +++ b/OpenSim/Framework/Servers/ServerBase.cs @@ -256,6 +256,12 @@ namespace OpenSim.Framework.Servers "Show thread status. Synonym for \"show threads\"", (string module, string[] args) => Notice(GetThreadsReport())); + m_console.Commands.AddCommand ( + "Debug", false, "debug comms set", + "debug comms set serialosdreq true|false", + "Set comms parameters. For debug purposes.", + HandleDebugCommsSet); + m_console.Commands.AddCommand ( "Debug", false, "debug threadpool set", "debug threadpool set worker|iocp min|max ", @@ -284,11 +290,42 @@ namespace OpenSim.Framework.Servers public void RegisterCommonComponents(IConfigSource configSource) { + IConfig networkConfig = configSource.Configs["Network"]; + + if (networkConfig != null) + { + WebUtil.SerializeOSDRequestsPerEndpoint = networkConfig.GetBoolean("SerializeOSDRequests", false); + } + m_serverStatsCollector = new ServerStatsCollector(); m_serverStatsCollector.Initialise(configSource); m_serverStatsCollector.Start(); } + private void HandleDebugCommsSet(string module, string[] args) + { + if (args.Length != 5) + { + Notice("Usage: debug comms set serialosdreq true|false"); + return; + } + + if (args[3] != "serialosdreq") + { + Notice("Usage: debug comms set serialosdreq true|false"); + return; + } + + bool setSerializeOsdRequests; + + if (!ConsoleUtil.TryParseConsoleBool(m_console, args[4], out setSerializeOsdRequests)) + return; + + WebUtil.SerializeOSDRequestsPerEndpoint = setSerializeOsdRequests; + + Notice("serialosdreq is now {0}", setSerializeOsdRequests); + } + private void HandleDebugThreadpoolSet(string module, string[] args) { if (args.Length != 6) diff --git a/OpenSim/Framework/WebUtil.cs b/OpenSim/Framework/WebUtil.cs index 0e9de59376..706b33ff4a 100644 --- a/OpenSim/Framework/WebUtil.cs +++ b/OpenSim/Framework/WebUtil.cs @@ -66,6 +66,11 @@ namespace OpenSim.Framework /// public static int RequestNumber { get; internal set; } + /// + /// Control where OSD requests should be serialized per endpoint. + /// + public static bool SerializeOSDRequestsPerEndpoint { get; set; } + /// /// this is the header field used to communicate the local request id /// used for performance and debugging @@ -145,10 +150,17 @@ namespace OpenSim.Framework public static OSDMap ServiceOSDRequest(string url, OSDMap data, string method, int timeout, bool compressed) { - //lock (EndPointLock(url)) - //{ - return ServiceOSDRequestWorker(url,data,method,timeout,compressed); - //} + if (SerializeOSDRequestsPerEndpoint) + { + lock (EndPointLock(url)) + { + return ServiceOSDRequestWorker(url, data, method, timeout, compressed); + } + } + else + { + return ServiceOSDRequestWorker(url, data, method, timeout, compressed); + } } public static void LogOutgoingDetail(Stream outputStream) From 4581bdd929d84abe2dbdc46c819d015e391a5b6d Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Mon, 5 Aug 2013 23:49:33 +0100 Subject: [PATCH 26/33] Add "debug comms status" command to show current debug comms settings --- OpenSim/Framework/Servers/ServerBase.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/OpenSim/Framework/Servers/ServerBase.cs b/OpenSim/Framework/Servers/ServerBase.cs index 824c7e2431..1bee6a3438 100644 --- a/OpenSim/Framework/Servers/ServerBase.cs +++ b/OpenSim/Framework/Servers/ServerBase.cs @@ -262,6 +262,12 @@ namespace OpenSim.Framework.Servers "Set comms parameters. For debug purposes.", HandleDebugCommsSet); + m_console.Commands.AddCommand ( + "Debug", false, "debug comms status", + "debug comms status", + "Show current debug comms parameters.", + HandleDebugCommsStatus); + m_console.Commands.AddCommand ( "Debug", false, "debug threadpool set", "debug threadpool set worker|iocp min|max ", @@ -302,6 +308,11 @@ namespace OpenSim.Framework.Servers m_serverStatsCollector.Start(); } + private void HandleDebugCommsStatus(string module, string[] args) + { + Notice("serialosdreq is {0}", WebUtil.SerializeOSDRequestsPerEndpoint); + } + private void HandleDebugCommsSet(string module, string[] args) { if (args.Length != 5) From ac198068ab7bb3895d95c6d1902b2c6af575a32a Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 6 Aug 2013 00:00:12 +0100 Subject: [PATCH 27/33] Add "debug threadpool status" console command to show min/max/current worker/iocp threadpool numbers --- OpenSim/Framework/Servers/ServerBase.cs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/OpenSim/Framework/Servers/ServerBase.cs b/OpenSim/Framework/Servers/ServerBase.cs index 1bee6a3438..c258ff6403 100644 --- a/OpenSim/Framework/Servers/ServerBase.cs +++ b/OpenSim/Framework/Servers/ServerBase.cs @@ -274,6 +274,12 @@ namespace OpenSim.Framework.Servers "Set threadpool parameters. For debug purposes.", HandleDebugThreadpoolSet); + m_console.Commands.AddCommand ( + "Debug", false, "debug threadpool status", + "debug threadpool status", + "Show current debug threadpool parameters.", + HandleDebugThreadpoolStatus); + m_console.Commands.AddCommand( "Debug", false, "force gc", "force gc", @@ -337,6 +343,23 @@ namespace OpenSim.Framework.Servers Notice("serialosdreq is now {0}", setSerializeOsdRequests); } + private void HandleDebugThreadpoolStatus(string module, string[] args) + { + int workerThreads, iocpThreads; + + ThreadPool.GetMinThreads(out workerThreads, out iocpThreads); + Notice("Min worker threads: {0}", workerThreads); + Notice("Min IOCP threads: {0}", iocpThreads); + + ThreadPool.GetMaxThreads(out workerThreads, out iocpThreads); + Notice("Max worker threads: {0}", workerThreads); + Notice("Max IOCP threads: {0}", iocpThreads); + + ThreadPool.GetAvailableThreads(out workerThreads, out iocpThreads); + Notice("Available worker threads: {0}", workerThreads); + Notice("Available IOCP threads: {0}", iocpThreads); + } + private void HandleDebugThreadpoolSet(string module, string[] args) { if (args.Length != 6) From 4c2f6de8e4957df3c7186437089ba0925edb1a08 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 6 Aug 2013 18:29:33 +0100 Subject: [PATCH 28/33] Add the experimental ability to dump stats (result of command "show stats all") to file OpenSimStats.log every 5 seconds. This can currently only be activated with the console command "debug stats record start". Off by default. Records to file OpenSimStats.log for simulator and RobustStats.log for ROBUST --- OpenSim/Framework/Monitoring/StatsManager.cs | 52 +++++++++++++++----- bin/OpenSim.32BitLaunch.exe.config | 36 +++++++++++++- bin/OpenSim.exe.config | 21 ++++++++ bin/Robust.32BitLaunch.exe.config | 22 +++++++++ bin/Robust.exe.config | 21 ++++++++ 5 files changed, 139 insertions(+), 13 deletions(-) diff --git a/OpenSim/Framework/Monitoring/StatsManager.cs b/OpenSim/Framework/Monitoring/StatsManager.cs index 87197f422f..c8e838cadf 100644 --- a/OpenSim/Framework/Monitoring/StatsManager.cs +++ b/OpenSim/Framework/Monitoring/StatsManager.cs @@ -81,6 +81,8 @@ namespace OpenSim.Framework.Monitoring + "More than one name can be given separated by spaces.\n" + "THIS STATS FACILITY IS EXPERIMENTAL AND DOES NOT YET CONTAIN ALL STATS", HandleShowStatsCommand); + + StatsLogger.RegisterConsoleCommands(console); } public static void HandleShowStatsCommand(string module, string[] cmd) @@ -145,29 +147,55 @@ namespace OpenSim.Framework.Monitoring } } + public static List GetAllStatsReports() + { + List reports = new List(); + + foreach (var category in RegisteredStats.Values) + reports.AddRange(GetCategoryStatsReports(category)); + + return reports; + } + private static void OutputAllStatsToConsole(ICommandConsole con) { - foreach (var category in RegisteredStats.Values) - { - OutputCategoryStatsToConsole(con, category); - } + foreach (string report in GetAllStatsReports()) + con.Output(report); + } + + private static List GetCategoryStatsReports( + SortedDictionary> category) + { + List reports = new List(); + + foreach (var container in category.Values) + reports.AddRange(GetContainerStatsReports(container)); + + return reports; } private static void OutputCategoryStatsToConsole( ICommandConsole con, SortedDictionary> category) { - foreach (var container in category.Values) - { - OutputContainerStatsToConsole(con, container); - } + foreach (string report in GetCategoryStatsReports(category)) + con.Output(report); } - private static void OutputContainerStatsToConsole( ICommandConsole con, SortedDictionary container) + private static List GetContainerStatsReports(SortedDictionary container) { + List reports = new List(); + foreach (Stat stat in container.Values) - { - con.Output(stat.ToConsoleString()); - } + reports.Add(stat.ToConsoleString()); + + return reports; + } + + private static void OutputContainerStatsToConsole( + ICommandConsole con, SortedDictionary container) + { + foreach (string report in GetContainerStatsReports(container)) + con.Output(report); } // Creates an OSDMap of the format: diff --git a/bin/OpenSim.32BitLaunch.exe.config b/bin/OpenSim.32BitLaunch.exe.config index 6ac0206e6c..6a6b3c8768 100644 --- a/bin/OpenSim.32BitLaunch.exe.config +++ b/bin/OpenSim.32BitLaunch.exe.config @@ -11,22 +11,56 @@ + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bin/OpenSim.exe.config b/bin/OpenSim.exe.config index 8a891f4917..b2cb4e5b81 100755 --- a/bin/OpenSim.exe.config +++ b/bin/OpenSim.exe.config @@ -11,6 +11,10 @@ + + + + @@ -21,11 +25,23 @@ + + + + + + + + + + + + @@ -42,5 +58,10 @@ + + + + + diff --git a/bin/Robust.32BitLaunch.exe.config b/bin/Robust.32BitLaunch.exe.config index dae45ffaaa..ec17049a84 100644 --- a/bin/Robust.32BitLaunch.exe.config +++ b/bin/Robust.32BitLaunch.exe.config @@ -11,22 +11,44 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/bin/Robust.exe.config b/bin/Robust.exe.config index 4914f55cb2..62975fd6a1 100644 --- a/bin/Robust.exe.config +++ b/bin/Robust.exe.config @@ -11,6 +11,10 @@ + + + + @@ -19,15 +23,32 @@ + + + + + + + + + + + + + + + + + From d6d5d4ebd033d47886c6e31ae87c0be527f5545e Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 6 Aug 2013 18:32:16 +0100 Subject: [PATCH 29/33] Add file missing from last commit 4c2f6de --- OpenSim/Framework/Monitoring/StatsLogger.cs | 108 ++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 OpenSim/Framework/Monitoring/StatsLogger.cs diff --git a/OpenSim/Framework/Monitoring/StatsLogger.cs b/OpenSim/Framework/Monitoring/StatsLogger.cs new file mode 100644 index 0000000000..fa2e1b641e --- /dev/null +++ b/OpenSim/Framework/Monitoring/StatsLogger.cs @@ -0,0 +1,108 @@ +/* + * 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.Reflection; +using System.Timers; +using log4net; + +namespace OpenSim.Framework.Monitoring +{ + /// + /// Provides a means to continuously log stats for debugging purposes. + /// + public static class StatsLogger + { + private static readonly ILog m_statsLog = LogManager.GetLogger("special.StatsLogger"); + + private static Timer m_loggingTimer; + private static int m_statsLogIntervalMs = 5000; + + public static void RegisterConsoleCommands(ICommandConsole console) + { + console.Commands.AddCommand( + "Debug", + false, + "debug stats record", + "debug stats record start|stop", + "Control whether stats are being regularly recorded to a separate file.", + "For debug purposes. Experimental.", + HandleStatsRecordCommand); + } + + public static void HandleStatsRecordCommand(string module, string[] cmd) + { + ICommandConsole con = MainConsole.Instance; + + if (cmd.Length != 4) + { + con.Output("Usage: debug stats record start|stop"); + return; + } + + if (cmd[3] == "start") + { + Start(); + con.OutputFormat("Now recording all stats very {0}ms to file", m_statsLogIntervalMs); + } + else if (cmd[3] == "stop") + { + Stop(); + con.Output("Stopped recording stats to file."); + } + } + + public static void Start() + { + if (m_loggingTimer != null) + Stop(); + + m_loggingTimer = new Timer(m_statsLogIntervalMs); + m_loggingTimer.AutoReset = false; + m_loggingTimer.Elapsed += Log; + m_loggingTimer.Start(); + } + + public static void Stop() + { + if (m_loggingTimer != null) + { + m_loggingTimer.Stop(); + } + } + + private static void Log(object sender, ElapsedEventArgs e) + { + m_statsLog.InfoFormat("*** STATS REPORT AT {0} ***", DateTime.Now); + + foreach (string report in StatsManager.GetAllStatsReports()) + m_statsLog.Info(report); + + m_loggingTimer.Start(); + } + } +} \ No newline at end of file From 3194ffdab8d54723ad1546846c1d45472d6a8464 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Wed, 7 Aug 2013 08:01:59 -0700 Subject: [PATCH 30/33] Fixed incomplete commit r/23317 -- see_into_region. Put the guard around estate bans also, and delete the obsolete config var. --- .../Region/Application/ConfigurationLoader.cs | 1 - OpenSim/Region/Framework/Scenes/Scene.cs | 32 +++++++++---------- .../Tools/Configger/ConfigurationLoader.cs | 1 - 3 files changed, 16 insertions(+), 18 deletions(-) diff --git a/OpenSim/Region/Application/ConfigurationLoader.cs b/OpenSim/Region/Application/ConfigurationLoader.cs index fc3999f7a6..3e9363808b 100644 --- a/OpenSim/Region/Application/ConfigurationLoader.cs +++ b/OpenSim/Region/Application/ConfigurationLoader.cs @@ -337,7 +337,6 @@ namespace OpenSim config.Set("physics", "OpenDynamicsEngine"); config.Set("meshing", "Meshmerizer"); config.Set("physical_prim", true); - config.Set("see_into_this_sim_from_neighbor", true); config.Set("serverside_object_permissions", true); config.Set("storage_plugin", "OpenSim.Data.SQLite.dll"); config.Set("storage_connection_string", "URI=file:OpenSim.db,version=3"); diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index dec493bfc3..503b81af53 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -4013,28 +4013,28 @@ namespace OpenSim.Region.Framework.Scenes } } - if (RegionInfo.EstateSettings != null) - { - if (RegionInfo.EstateSettings.IsBanned(agent.AgentID)) - { - m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", - agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); - reason = String.Format("Denied access to region {0}: You have been banned from that region.", - RegionInfo.RegionName); - return false; - } - } - else - { - m_log.ErrorFormat("[CONNECTION BEGIN]: Estate Settings is null!"); - } - // We only test the things below when we want to cut off // child agents from being present in the scene for which their root // agent isn't allowed. Otherwise, we allow child agents. The test for // the root is done elsewhere (QueryAccess) if (!bypassAccessControl) { + if (RegionInfo.EstateSettings != null) + { + if (RegionInfo.EstateSettings.IsBanned(agent.AgentID)) + { + m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", + agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); + reason = String.Format("Denied access to region {0}: You have been banned from that region.", + RegionInfo.RegionName); + return false; + } + } + else + { + m_log.ErrorFormat("[CONNECTION BEGIN]: Estate Settings is null!"); + } + List agentGroups = new List(); if (m_groupsModule != null) diff --git a/OpenSim/Tools/Configger/ConfigurationLoader.cs b/OpenSim/Tools/Configger/ConfigurationLoader.cs index 28bcc99ff4..72ba18526f 100644 --- a/OpenSim/Tools/Configger/ConfigurationLoader.cs +++ b/OpenSim/Tools/Configger/ConfigurationLoader.cs @@ -239,7 +239,6 @@ namespace OpenSim.Tools.Configger config.Set("physics", "OpenDynamicsEngine"); config.Set("meshing", "Meshmerizer"); config.Set("physical_prim", true); - config.Set("see_into_this_sim_from_neighbor", true); config.Set("serverside_object_permissions", true); config.Set("storage_plugin", "OpenSim.Data.SQLite.dll"); config.Set("storage_connection_string", "URI=file:OpenSim.db,version=3"); From dbd773e89e1956144d0358033e560fbd36c89ecd Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Wed, 7 Aug 2013 10:04:53 -0700 Subject: [PATCH 31/33] Amend to last commit -- remove the obsolete var from OpenSim.ini.example --- bin/OpenSim.ini.example | 4 ---- 1 file changed, 4 deletions(-) diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index 33f3263c7e..d6de777632 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -184,10 +184,6 @@ ;; if the first change occurred this number of seconds ago. ; MaximumTimeBeforePersistenceConsidered = 600 - ;# {see_into_this_sim_from_neighbor} {} {Should avatars in neighbor sims see objects in this sim?} {true false} true - ;; Should avatars in neighbor sims see objects in this sim? - ; see_into_this_sim_from_neighbor = true - ;# {physical_prim} {} {Allow prims to be physical?} {true false} true ;; if you would like to allow prims to be physical and move by physics ;; with the physical checkbox in the client set this to true. From a33a1ac958b3158c9ce009e5d2915c165fb11c23 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Wed, 7 Aug 2013 18:52:30 +0100 Subject: [PATCH 32/33] Add post-CreateAgent teleport cancellation/abortion functionality from v1 transfer protocol into v2. This stops OpenSimulator still trying to teleport the user if they hit cancel on the teleport screen or closed the viewer whilst the protocol was trying to create an agent on the remote region. Ideally, the code may also attempt to tell the destination simulator that the agent should be removed (accounting for issues where the destination was not responding in the first place, etc.) --- .../EntityTransfer/EntityTransferModule.cs | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 96cd6b9e6c..80c125a660 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -956,6 +956,27 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer return; } + if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Cancelling) + { + m_interRegionTeleportCancels.Value++; + + m_log.DebugFormat( + "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after CreateAgent on client request", + sp.Name, finalDestination.RegionName, sp.Scene.Name); + + return; + } + else if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting) + { + m_interRegionTeleportAborts.Value++; + + m_log.DebugFormat( + "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after CreateAgent due to previous client close.", + sp.Name, finalDestination.RegionName, sp.Scene.Name); + + return; + } + // Past this point we have to attempt clean up if the teleport fails, so update transfer state. m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring); From b10710d4a5f7fb33ee9b90aefac16ac3d4647db6 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Wed, 7 Aug 2013 23:17:31 +0100 Subject: [PATCH 33/33] minor: add some method doc to ScenePresence fields used for entity transfer, add minor details to some log messages, rename a misleading local variable name. No functional changes. --- OpenSim/Framework/ChildAgentDataUpdate.cs | 6 +++++ .../EntityTransfer/EntityTransferModule.cs | 14 ++++++---- OpenSim/Region/Framework/Scenes/Scene.cs | 26 +++++++++++------- .../Region/Framework/Scenes/ScenePresence.cs | 27 ++++++++++++------- 4 files changed, 48 insertions(+), 25 deletions(-) diff --git a/OpenSim/Framework/ChildAgentDataUpdate.cs b/OpenSim/Framework/ChildAgentDataUpdate.cs index 1c5f558b42..18d008c654 100644 --- a/OpenSim/Framework/ChildAgentDataUpdate.cs +++ b/OpenSim/Framework/ChildAgentDataUpdate.cs @@ -287,6 +287,12 @@ namespace OpenSim.Framework public Vector3 AtAxis; public Vector3 LeftAxis; public Vector3 UpAxis; + + /// + /// Signal on a V2 teleport that Scene.IncomingChildAgentDataUpdate(AgentData ad) should wait for the + /// scene presence to become root (triggered when the viewer sends a CompleteAgentMovement UDP packet after + /// establishing the connection triggered by it's receipt of a TeleportFinish EQ message). + /// public bool SenderWantsToWaitForRoot; public float Far; diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 80c125a660..01ef710387 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -688,8 +688,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer if (version.Equals("SIMULATION/0.2")) TransferAgent_V2(sp, agentCircuit, reg, finalDestination, endPoint, teleportFlags, oldRegionX, newRegionX, oldRegionY, newRegionY, version, out reason); else - TransferAgent_V1(sp, agentCircuit, reg, finalDestination, endPoint, teleportFlags, oldRegionX, newRegionX, oldRegionY, newRegionY, version, out reason); - + TransferAgent_V1(sp, agentCircuit, reg, finalDestination, endPoint, teleportFlags, oldRegionX, newRegionX, oldRegionY, newRegionY, version, out reason); } private void TransferAgent_V1(ScenePresence sp, AgentCircuitData agentCircuit, GridRegion reg, GridRegion finalDestination, @@ -698,7 +697,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer ulong destinationHandle = finalDestination.RegionHandle; AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode); - m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Using TP V1"); + m_log.DebugFormat( + "[ENTITY TRANSFER MODULE]: Using TP V1 for {0} going from {1} to {2}", + sp.Name, Scene.Name, finalDestination.RegionName); + // Let's create an agent there if one doesn't exist yet. // NOTE: logout will always be false for a non-HG teleport. bool logout = false; @@ -1079,20 +1081,22 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer if (!sp.DoNotCloseAfterTeleport) { // OK, it got this agent. Let's close everything - m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Closing in agent {0} in region {1}", sp.Name, Scene.RegionInfo.RegionName); + m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Closing in agent {0} in region {1}", sp.Name, Scene.Name); sp.CloseChildAgents(newRegionX, newRegionY); sp.Scene.IncomingCloseAgent(sp.UUID, false); } else { - m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Not closing agent {0}, user is back in {0}", sp.Name, Scene.RegionInfo.RegionName); + m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Not closing agent {0}, user is back in {0}", sp.Name, Scene.Name); sp.DoNotCloseAfterTeleport = false; } } else + { // now we have a child agent in this region. sp.Reset(); + } } /// diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 503b81af53..56cd57e9df 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -4222,36 +4222,42 @@ namespace OpenSim.Region.Framework.Scenes } // We have to wait until the viewer contacts this region - // after receiving the EnableSimulator HTTP Event Queue message. This triggers the viewer to send + // after receiving the EnableSimulator HTTP Event Queue message (for the v1 teleport protocol) + // or TeleportFinish (for the v2 teleport protocol). This triggers the viewer to send // a UseCircuitCode packet which in turn calls AddNewClient which finally creates the ScenePresence. - ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID); + ScenePresence sp = WaitGetScenePresence(cAgentData.AgentID); - if (childAgentUpdate != null) + if (sp != null) { - if (cAgentData.SessionID != childAgentUpdate.ControllingClient.SessionId) + if (cAgentData.SessionID != sp.ControllingClient.SessionId) { - m_log.WarnFormat("[SCENE]: Attempt to update agent {0} with invalid session id {1} (possibly from simulator in older version; tell them to update).", childAgentUpdate.UUID, cAgentData.SessionID); + m_log.WarnFormat( + "[SCENE]: Attempt to update agent {0} with invalid session id {1} (possibly from simulator in older version; tell them to update).", + sp.UUID, cAgentData.SessionID); + Console.WriteLine(String.Format("[SCENE]: Attempt to update agent {0} ({1}) with invalid session id {2}", - childAgentUpdate.UUID, childAgentUpdate.ControllingClient.SessionId, cAgentData.SessionID)); + sp.UUID, sp.ControllingClient.SessionId, cAgentData.SessionID)); } - childAgentUpdate.ChildAgentDataUpdate(cAgentData); + sp.ChildAgentDataUpdate(cAgentData); int ntimes = 20; if (cAgentData.SenderWantsToWaitForRoot) { - while (childAgentUpdate.IsChildAgent && ntimes-- > 0) + while (sp.IsChildAgent && ntimes-- > 0) Thread.Sleep(1000); m_log.DebugFormat( "[SCENE]: Found presence {0} {1} {2} in {3} after {4} waits", - childAgentUpdate.Name, childAgentUpdate.UUID, childAgentUpdate.IsChildAgent ? "child" : "root", RegionInfo.RegionName, 20 - ntimes); + sp.Name, sp.UUID, sp.IsChildAgent ? "child" : "root", Name, 20 - ntimes); - if (childAgentUpdate.IsChildAgent) + if (sp.IsChildAgent) return false; } + return true; } + return false; } diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 0ba2dabe5e..7fd13027aa 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -285,10 +285,24 @@ namespace OpenSim.Region.Framework.Scenes /// private Vector3 posLastSignificantMove; - // For teleports and crossings callbacks + #region For teleports and crossings callbacks + + /// + /// In the V1 teleport protocol, the destination simulator sends ReleaseAgent to this address. + /// string m_callbackURI; + UUID m_originRegionID; + /// + /// Used by the entity transfer module to signal when the presence should not be closed because a subsequent + /// teleport is reusing the connection. + /// + /// May be refactored or move somewhere else soon. + public bool DoNotCloseAfterTeleport { get; set; } + + #endregion + /// /// Script engines present in the scene /// @@ -717,13 +731,6 @@ namespace OpenSim.Region.Framework.Scenes } } - /// - /// Used by the entity transfer module to signal when the presence should not be closed because a subsequent - /// teleport is reusing the connection. - /// - /// May be refactored or move somewhere else soon. - public bool DoNotCloseAfterTeleport { get; set; } - private float m_speedModifier = 1.0f; public float SpeedModifier @@ -1325,14 +1332,14 @@ namespace OpenSim.Region.Framework.Scenes int count = 20; while (m_originRegionID.Equals(UUID.Zero) && count-- > 0) { - m_log.DebugFormat("[SCENE PRESENCE]: Agent {0} waiting for update in {1}", client.Name, Scene.RegionInfo.RegionName); + m_log.DebugFormat("[SCENE PRESENCE]: Agent {0} waiting for update in {1}", client.Name, Scene.Name); Thread.Sleep(200); } if (m_originRegionID.Equals(UUID.Zero)) { // Movement into region will fail - m_log.WarnFormat("[SCENE PRESENCE]: Update agent {0} never arrived", client.Name); + m_log.WarnFormat("[SCENE PRESENCE]: Update agent {0} never arrived in {1}", client.Name, Scene.Name); return false; }