From 2028787c0dee934eb97c07fe7d16909dc92789c3 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Sun, 13 Jan 2013 12:25:41 +0000 Subject: [PATCH 01/10] prevent potencial invalid refs --- .../UbitOdePlugin/ODERayCastRequestManager.cs | 207 ++++-------------- .../Region/Physics/UbitOdePlugin/OdeScene.cs | 16 +- 2 files changed, 53 insertions(+), 170 deletions(-) diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs index 7fe3109267..4f598ea41c 100644 --- a/OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs +++ b/OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs @@ -68,7 +68,6 @@ namespace OpenSim.Region.Physics.OdePlugin /// ODE near callback delegate /// private d.NearCallback nearCallback; - private d.NearCallback nearProbeCallback; private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private List m_contactResults = new List(); private RayFilterFlags CurrentRayFilter; @@ -78,7 +77,6 @@ namespace OpenSim.Region.Physics.OdePlugin { m_scene = pScene; nearCallback = near; - nearProbeCallback = nearProbe; ray = d.CreateRay(IntPtr.Zero, 1.0f); d.GeomSetCategoryBits(ray, 0); Box = d.CreateBox(IntPtr.Zero, 1.0f, 1.0f, 1.0f); @@ -125,6 +123,24 @@ namespace OpenSim.Region.Physics.OdePlugin { if (req.callbackMethod != null) { + IntPtr geom = IntPtr.Zero; + if (req.actor != null) + { + if (m_scene.haveActor(req.actor)) + { + if (req.actor is OdePrim) + geom = ((OdePrim)req.actor).prim_geom; + else if (req.actor is OdeCharacter) + geom = ((OdePrim)req.actor).prim_geom; + } + if (geom == IntPtr.Zero) + { + NoContacts(req); + continue; + } + } + + CurrentRayFilter = req.filter; CurrentMaxCount = req.Count; @@ -188,7 +204,7 @@ namespace OpenSim.Region.Physics.OdePlugin CollisionContactGeomsPerTest |= (int)d.CONTACTS_UNIMPORTANT; } - if (req.geom == IntPtr.Zero) + if (geom == IntPtr.Zero) { // translate ray filter to Collision flags catflags = 0; @@ -226,7 +242,7 @@ namespace OpenSim.Region.Physics.OdePlugin catflags |= CollisionCategories.Space; d.GeomSetCollideBits(Plane, (uint)catflags); d.GeomSetCategoryBits(Plane, (uint)catflags); - doPlane(req); + doPlane(req,IntPtr.Zero); } else { @@ -242,12 +258,12 @@ namespace OpenSim.Region.Physics.OdePlugin if (req.callbackMethod is ProbePlaneCallback) { d.GeomSetCollideBits(Plane, (uint)CollisionCategories.All); - doPlane(req); + doPlane(req,geom); } else { d.GeomSetCollideBits(ray, (uint)CollisionCategories.All); - doGeomRay(req); + doGeomRay(req,geom); } } } @@ -267,6 +283,23 @@ namespace OpenSim.Region.Physics.OdePlugin /// /// + private void NoContacts(ODERayRequest req) + { + if (req.callbackMethod is RaycastCallback) + { + ((RaycastCallback)req.callbackMethod)(false, Vector3.Zero, 0, 0, Vector3.Zero); + return; + } + List cresult = new List(); + + if (req.callbackMethod is RayCallback) + ((RayCallback)req.callbackMethod)(cresult); + else if (req.callbackMethod is ProbeBoxCallback) + ((ProbeBoxCallback)req.callbackMethod)(cresult); + else if (req.callbackMethod is ProbeSphereCallback) + ((ProbeSphereCallback)req.callbackMethod)(cresult); + } + private const RayFilterFlags FilterActiveSpace = RayFilterFlags.agent | RayFilterFlags.physical | RayFilterFlags.LSLPhanton; // private const RayFilterFlags FilterStaticSpace = RayFilterFlags.water | RayFilterFlags.land | RayFilterFlags.nonphysical | RayFilterFlags.LSLPhanton; private const RayFilterFlags FilterStaticSpace = RayFilterFlags.water | RayFilterFlags.nonphysical | RayFilterFlags.LSLPhanton; @@ -358,10 +391,10 @@ namespace OpenSim.Region.Physics.OdePlugin ((ProbeSphereCallback)req.callbackMethod)(cresult); } - private void doPlane(ODERayRequest req) + private void doPlane(ODERayRequest req,IntPtr geom) { // Collide tests - if (req.geom == IntPtr.Zero) + if (geom == IntPtr.Zero) { if ((CurrentRayFilter & FilterActiveSpace) != 0) { @@ -375,7 +408,7 @@ namespace OpenSim.Region.Physics.OdePlugin } else { - d.SpaceCollide2(Plane, req.geom, IntPtr.Zero, nearCallback); + d.SpaceCollide2(Plane, geom, IntPtr.Zero, nearCallback); } List cresult = new List(m_contactResults.Count); @@ -392,10 +425,10 @@ namespace OpenSim.Region.Physics.OdePlugin /// Method that actually initiates the raycast with a geom /// /// - private void doGeomRay(ODERayRequest req) + private void doGeomRay(ODERayRequest req, IntPtr geom) { // Collide test - d.SpaceCollide2(ray, req.geom, IntPtr.Zero, nearCallback); // still do this to have full AABB pre test + d.SpaceCollide2(ray, geom, IntPtr.Zero, nearCallback); // still do this to have full AABB pre test if (req.callbackMethod is RaycastCallback) { @@ -607,156 +640,6 @@ namespace OpenSim.Region.Physics.OdePlugin } } - private void nearProbe(IntPtr space, IntPtr g1, IntPtr g2) - { - if (g1 == IntPtr.Zero || g1 == g2) - return; - - if (m_contactResults.Count >= CurrentMaxCount) - return; - - if (d.GeomIsSpace(g1)) - { - try - { - d.SpaceCollide2(g1, g2, IntPtr.Zero, nearProbeCallback); - } - catch (Exception e) - { - m_log.WarnFormat("[PHYSICS Ray]: Unable to Space collide test an object: {0}", e.Message); - } - return; - } - - int count = 0; - try - { - count = d.CollidePtr(g1, g2, CollisionContactGeomsPerTest, m_scene.ContactgeomsArray, d.ContactGeom.unmanagedSizeOf); - } - catch (Exception e) - { - m_log.WarnFormat("[PHYSICS Ray]: Unable to collide test an object: {0}", e.Message); - return; - } - - if (count == 0) - return; - - uint ID = 0; - PhysicsActor p1 = null; - - m_scene.actor_name_map.TryGetValue(g1, out p1); - - if (p1 == null) - return; - - switch (p1.PhysicsActorType) - { - case (int)ActorTypes.Prim: - - RayFilterFlags thisFlags; - - if (p1.IsPhysical) - thisFlags = RayFilterFlags.physical; - else - thisFlags = RayFilterFlags.nonphysical; - - if (p1.Phantom) - thisFlags |= RayFilterFlags.phantom; - - if (p1.IsVolumeDtc) - thisFlags |= RayFilterFlags.volumedtc; - - if ((thisFlags & CurrentRayFilter) == 0) - return; - - ID = ((OdePrim)p1).LocalID; - break; - - case (int)ActorTypes.Agent: - - if ((CurrentRayFilter & RayFilterFlags.agent) == 0) - return; - else - ID = ((OdeCharacter)p1).LocalID; - break; - - case (int)ActorTypes.Ground: - - if ((CurrentRayFilter & RayFilterFlags.land) == 0) - return; - break; - - case (int)ActorTypes.Water: - - if ((CurrentRayFilter & RayFilterFlags.water) == 0) - return; - break; - - default: - break; - } - - d.ContactGeom curcontact = new d.ContactGeom(); - - // closestHit for now only works for meshs, so must do it for others - if ((CurrentRayFilter & RayFilterFlags.ClosestHit) == 0) - { - // Loop all contacts, build results. - for (int i = 0; i < count; i++) - { - if (!GetCurContactGeom(i, ref curcontact)) - break; - - ContactResult collisionresult = new ContactResult(); - collisionresult.ConsumerID = ID; - collisionresult.Pos.X = curcontact.pos.X; - collisionresult.Pos.Y = curcontact.pos.Y; - collisionresult.Pos.Z = curcontact.pos.Z; - collisionresult.Depth = curcontact.depth; - collisionresult.Normal.X = curcontact.normal.X; - collisionresult.Normal.Y = curcontact.normal.Y; - collisionresult.Normal.Z = curcontact.normal.Z; - lock (m_contactResults) - { - m_contactResults.Add(collisionresult); - if (m_contactResults.Count >= CurrentMaxCount) - return; - } - } - } - else - { - // keep only closest contact - ContactResult collisionresult = new ContactResult(); - collisionresult.ConsumerID = ID; - collisionresult.Depth = float.MaxValue; - - for (int i = 0; i < count; i++) - { - if (!GetCurContactGeom(i, ref curcontact)) - break; - - if (curcontact.depth < collisionresult.Depth) - { - collisionresult.Pos.X = curcontact.pos.X; - collisionresult.Pos.Y = curcontact.pos.Y; - collisionresult.Pos.Z = curcontact.pos.Z; - collisionresult.Depth = curcontact.depth; - collisionresult.Normal.X = curcontact.normal.X; - collisionresult.Normal.Y = curcontact.normal.Y; - collisionresult.Normal.Z = curcontact.normal.Z; - } - } - - if (collisionresult.Depth != float.MaxValue) - { - lock (m_contactResults) - m_contactResults.Add(collisionresult); - } - } - } - /// /// Dereference the creator scene so that it can be garbage collected if needed. /// @@ -788,7 +671,7 @@ namespace OpenSim.Region.Physics.OdePlugin public struct ODERayRequest { - public IntPtr geom; + public PhysicsActor actor; public Vector3 Origin; public Vector3 Normal; public int Count; diff --git a/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs b/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs index 0d18adb04d..51132104ad 100644 --- a/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs +++ b/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs @@ -2580,7 +2580,7 @@ namespace OpenSim.Region.Physics.OdePlugin if (retMethod != null) { ODERayRequest req = new ODERayRequest(); - req.geom = IntPtr.Zero; + req.actor = null; req.callbackMethod = retMethod; req.length = length; req.Normal = direction; @@ -2597,7 +2597,7 @@ namespace OpenSim.Region.Physics.OdePlugin if (retMethod != null) { ODERayRequest req = new ODERayRequest(); - req.geom = IntPtr.Zero; + req.actor = null; req.callbackMethod = retMethod; req.length = length; req.Normal = direction; @@ -2625,7 +2625,7 @@ namespace OpenSim.Region.Physics.OdePlugin }; ODERayRequest req = new ODERayRequest(); - req.geom = IntPtr.Zero; + req.actor = null; req.callbackMethod = retMethod; req.length = length; req.Normal = direction; @@ -2663,7 +2663,7 @@ namespace OpenSim.Region.Physics.OdePlugin }; ODERayRequest req = new ODERayRequest(); - req.geom = IntPtr.Zero; + req.actor = null; req.callbackMethod = retMethod; req.length = length; req.Normal = direction; @@ -2710,7 +2710,7 @@ namespace OpenSim.Region.Physics.OdePlugin }; ODERayRequest req = new ODERayRequest(); - req.geom = geom; + req.actor = actor; req.callbackMethod = retMethod; req.length = length; req.Normal = direction; @@ -2745,7 +2745,7 @@ namespace OpenSim.Region.Physics.OdePlugin }; ODERayRequest req = new ODERayRequest(); - req.geom = IntPtr.Zero; + req.actor = null; req.callbackMethod = retMethod; req.Normal = size; req.Origin = position; @@ -2777,7 +2777,7 @@ namespace OpenSim.Region.Physics.OdePlugin }; ODERayRequest req = new ODERayRequest(); - req.geom = IntPtr.Zero; + req.actor = null; req.callbackMethod = retMethod; req.length = radius; req.Origin = position; @@ -2819,7 +2819,7 @@ namespace OpenSim.Region.Physics.OdePlugin }; ODERayRequest req = new ODERayRequest(); - req.geom = geom; + req.actor = null; req.callbackMethod = retMethod; req.length = plane.W; req.Normal.X = plane.X; From b263587e2104f304f084c72fcb0cc1d155dacc1e Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Sun, 13 Jan 2013 15:25:51 +0000 Subject: [PATCH 02/10] try to patch getmesh Throttle (test) --- .../Region/ClientStack/Linden/Caps/GetMeshModule.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs index 908f628274..6ec111539c 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs @@ -501,7 +501,8 @@ namespace OpenSim.Region.ClientStack.Linden ScenePresence p; if (m_scene.TryGetScenePresence(User, out p)) // If we don't get a user they're not here anymore. { - AlterThrottle(UserSetThrottle, p); +// AlterThrottle(UserSetThrottle, p); + UpdateThrottle(UserSetThrottle, p); } } } @@ -546,7 +547,12 @@ namespace OpenSim.Region.ClientStack.Linden // Client set throttle ! UserSetThrottle = pimagethrottle; CapSetThrottle = (int)(pimagethrottle*CapThrottleDistributon); - UDPSetThrottle = (int) (pimagethrottle*(100 - CapThrottleDistributon)); +// UDPSetThrottle = (int) (pimagethrottle*(100 - CapThrottleDistributon)); + + float udp = 1.0f - CapThrottleDistributon; + if(udp < 0.5f) + udp = 0.5f; + UDPSetThrottle = (int) ((float)pimagethrottle * udp); if (CapSetThrottle < 4068) CapSetThrottle = 4068; // at least two discovery mesh p.ControllingClient.SetAgentThrottleSilent((int) Throttle, UDPSetThrottle); From b3939a431cc28a5e3443ea1abcf1b4dbc48d7d3b Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 15 Jan 2013 22:15:06 +0100 Subject: [PATCH 03/10] Fix llSetRegionPos and detail behaviors of llSet[Link]PrimitiveParams[Fast]() regarding prim positioning. --- .../Shared/Api/Implementation/LSL_Api.cs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 1e1e574698..525e575b0e 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -2260,7 +2260,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return end; } - protected LSL_Vector GetSetPosTarget(SceneObjectPart part, LSL_Vector targetPos, LSL_Vector fromPos) + protected LSL_Vector GetSetPosTarget(SceneObjectPart part, LSL_Vector targetPos, LSL_Vector fromPos, bool adjust) { if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) return fromPos; @@ -2276,9 +2276,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if ((targetPos.z < ground) && disable_underground_movement && m_host.ParentGroup.AttachmentPoint == 0) targetPos.z = ground; } - LSL_Vector real_vec = SetPosAdjust(fromPos, targetPos); + if (adjust) + return SetPosAdjust(fromPos, targetPos); - return real_vec; + return targetPos; } /// @@ -2293,7 +2294,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return; LSL_Vector currentPos = GetPartLocalPos(part); - LSL_Vector toPos = GetSetPosTarget(part, targetPos, currentPos); + LSL_Vector toPos = GetSetPosTarget(part, targetPos, currentPos, adjust); if (part.ParentGroup.RootPart == part) @@ -7925,7 +7926,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return null; v=rules.GetVector3Item(idx++); - currentPosition = GetSetPosTarget(part, v, currentPosition); + if (part.IsRoot && !part.ParentGroup.IsAttachment) + currentPosition = GetSetPosTarget(part, v, currentPosition, true); + else + currentPosition = GetSetPosTarget(part, v, currentPosition, false); positionChanged = true; break; From b5f5400e069bcc8cb720391eccea385a45bfe7b5 Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 15 Jan 2013 22:15:58 +0100 Subject: [PATCH 04/10] Add Refresh() Method to ISerachModule to allow forcing a sim to resend it's search data --- OpenSim/Region/Framework/Interfaces/ISearchModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Interfaces/ISearchModule.cs b/OpenSim/Region/Framework/Interfaces/ISearchModule.cs index 64bf72cf86..d56d188da6 100644 --- a/OpenSim/Region/Framework/Interfaces/ISearchModule.cs +++ b/OpenSim/Region/Framework/Interfaces/ISearchModule.cs @@ -31,6 +31,6 @@ namespace OpenSim.Framework { public interface ISearchModule { - + void Refresh(); } } From 451b6c0e82f0bf850c5e2da1aafbcd48d676dc52 Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 16 Jan 2013 14:52:04 +0100 Subject: [PATCH 05/10] Add admin_refresh_search command to RemoteAdmin --- .../RemoteController/RemoteAdminPlugin.cs | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs index 3d80eb6899..9f3844bf38 100644 --- a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs +++ b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs @@ -157,6 +157,9 @@ namespace OpenSim.ApplicationPlugins.RemoteController availableMethods["admin_acl_remove"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcAccessListRemove); availableMethods["admin_acl_list"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcAccessListList); + // Misc + availableMethods["admin_refresh_search"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcRefreshSearch); + // Either enable full remote functionality or just selected features string enabledMethods = m_config.GetString("enabled_methods", "all"); @@ -1948,6 +1951,32 @@ namespace OpenSim.ApplicationPlugins.RemoteController responseData["success"] = true; } + private void XmlRpcRefreshSearch(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient) + { + m_log.Info("[RADMIN]: Received Refresh Search Request"); + + Hashtable responseData = (Hashtable)response.Value; + Hashtable requestData = (Hashtable)request.Params[0]; + + CheckRegionParams(requestData, responseData); + + Scene scene = null; + GetSceneFromRegionParams(requestData, responseData, out scene); + + ISearchModule searchModule = scene.RequestModuleInterface(); + if (searchModule != null) + { + searchModule.Refresh(); + responseData["success"] = true; + } + else + { + responseData["success"] = false; + } + + m_log.Info("[RADMIN]: Refresh Search Request complete"); + } + /// /// Parse a float with the given parameter name from a request data hash table. /// From 4d92c6b39f3ebb7a27517493b66d097d9d9d23dd Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Wed, 16 Jan 2013 15:30:58 +0000 Subject: [PATCH 06/10] fix STATE udp queue data rate since it is in use again, after being removed by intel folks (?)( should it be used or removed ??) --- OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs index f675377083..6485c1ac62 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs @@ -339,7 +339,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP int texture = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); // State is a subcategory of task that we allocate a percentage to - int state = 0; +// int state = 0; + int state = (int)((1.0f - STATE_TASK_PERCENTAGE) * (float)task); + task = (int)(STATE_TASK_PERCENTAGE * (float)task); // Make sure none of the throttles are set below our packet MTU, // otherwise a throttle could become permanently clogged @@ -350,6 +352,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP task = Math.Max(task, LLUDPServer.MTU); texture = Math.Max(texture, LLUDPServer.MTU); asset = Math.Max(asset, LLUDPServer.MTU); + state = Math.Max(state, LLUDPServer.MTU); //int total = resend + land + wind + cloud + task + texture + asset; //m_log.DebugFormat("[LLUDPCLIENT]: {0} is setting throttles. Resend={1}, Land={2}, Wind={3}, Cloud={4}, Task={5}, Texture={6}, Asset={7}, Total={8}", From d92d5ca1fd2f84841881f5822316b4ba225e679d Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 16 Jan 2013 16:46:43 +0100 Subject: [PATCH 07/10] Revert " fix STATE udp queue data rate since it is in use again, after being" This reverts commit 4d92c6b39f3ebb7a27517493b66d097d9d9d23dd. --- OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs index 6485c1ac62..f675377083 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs @@ -339,9 +339,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP int texture = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); // State is a subcategory of task that we allocate a percentage to -// int state = 0; - int state = (int)((1.0f - STATE_TASK_PERCENTAGE) * (float)task); - task = (int)(STATE_TASK_PERCENTAGE * (float)task); + int state = 0; // Make sure none of the throttles are set below our packet MTU, // otherwise a throttle could become permanently clogged @@ -352,7 +350,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP task = Math.Max(task, LLUDPServer.MTU); texture = Math.Max(texture, LLUDPServer.MTU); asset = Math.Max(asset, LLUDPServer.MTU); - state = Math.Max(state, LLUDPServer.MTU); //int total = resend + land + wind + cloud + task + texture + asset; //m_log.DebugFormat("[LLUDPCLIENT]: {0} is setting throttles. Resend={1}, Land={2}, Wind={3}, Cloud={4}, Task={5}, Texture={6}, Asset={7}, Total={8}", From 85aa1804dfc9edbf41f16c312d06746eecd59bc9 Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 16 Jan 2013 16:45:18 +0000 Subject: [PATCH 08/10] Complete removal of the now unused state queue --- OpenSim/Framework/ThrottleOutPacketType.cs | 4 ---- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 2 +- .../Region/ClientStack/Linden/UDP/LLUDPClient.cs | 15 ++------------- 3 files changed, 3 insertions(+), 18 deletions(-) diff --git a/OpenSim/Framework/ThrottleOutPacketType.cs b/OpenSim/Framework/ThrottleOutPacketType.cs index d56231a397..ca4b126c97 100644 --- a/OpenSim/Framework/ThrottleOutPacketType.cs +++ b/OpenSim/Framework/ThrottleOutPacketType.cs @@ -47,9 +47,6 @@ namespace OpenSim.Framework Texture = 5, /// Non-texture assets Asset = 6, - /// Avatar and primitive data - /// This is a sub-category of Task - State = 7, } [Flags] @@ -61,6 +58,5 @@ namespace OpenSim.Framework Task = 1 << 3, Texture = 1 << 4, Asset = 1 << 5, - State = 1 << 6, } } diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 0a865abcc8..3ae9dafd15 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -1607,7 +1607,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (localIDs.Count == 1 && m_scene.GetScenePresence(localIDs[0]) != null) { - OutPacket(kill, ThrottleOutPacketType.State); + OutPacket(kill, ThrottleOutPacketType.Task); } else { diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs index f675377083..f1a181209a 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs @@ -279,7 +279,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP public string GetStats() { return string.Format( - "{0,7} {1,7} {2,7} {3,9} {4,7} {5,7} {6,7} {7,7} {8,7} {9,8} {10,7} {11,7} {12,7}", + "{0,7} {1,7} {2,7} {3,9} {4,7} {5,7} {6,7} {7,7} {8,7} {9,8} {10,7} {11,7}", Util.EnvironmentTickCountSubtract(TickLastPacketReceived), PacketsReceived, PacketsSent, @@ -291,8 +291,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_packetOutboxes[(int)ThrottleOutPacketType.Cloud].Count, m_packetOutboxes[(int)ThrottleOutPacketType.Task].Count, m_packetOutboxes[(int)ThrottleOutPacketType.Texture].Count, - m_packetOutboxes[(int)ThrottleOutPacketType.Asset].Count, - m_packetOutboxes[(int)ThrottleOutPacketType.State].Count); + m_packetOutboxes[(int)ThrottleOutPacketType.Asset].Count); } public void SendPacketStats() @@ -338,8 +337,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP int task = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; int texture = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); - // State is a subcategory of task that we allocate a percentage to - int state = 0; // Make sure none of the throttles are set below our packet MTU, // otherwise a throttle could become permanently clogged @@ -376,9 +373,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP bucket = m_throttleCategories[(int)ThrottleOutPacketType.Task]; bucket.RequestedDripRate = task; - bucket = m_throttleCategories[(int)ThrottleOutPacketType.State]; - bucket.RequestedDripRate = state; - bucket = m_throttleCategories[(int)ThrottleOutPacketType.Texture]; bucket.RequestedDripRate = texture; @@ -709,9 +703,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP Texture = 5, /// Non-texture assets Asset = 6, - /// Avatar and primitive data - /// This is a sub-category of Task - State = 7, */ switch (category) @@ -728,8 +719,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP return ThrottleOutPacketTypeFlags.Texture; case ThrottleOutPacketType.Asset: return ThrottleOutPacketTypeFlags.Asset; - case ThrottleOutPacketType.State: - return ThrottleOutPacketTypeFlags.State; default: return 0; } From 91138014e21e19a3c02ee1640caab7f748472038 Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 16 Jan 2013 17:12:56 +0000 Subject: [PATCH 09/10] Change all uses of the removed state queue to the task queue for now. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 3ae9dafd15..956c2c9377 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -2788,7 +2788,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP Transfer.TransferInfo.Size = req.AssetInf.Data.Length; Transfer.TransferInfo.TransferID = req.TransferRequestID; Transfer.Header.Zerocoded = true; - OutPacket(Transfer, isWearable ? ThrottleOutPacketType.State : ThrottleOutPacketType.Asset); + OutPacket(Transfer, isWearable ? ThrottleOutPacketType.Task : ThrottleOutPacketType.Asset); if (req.NumPackets == 1) { @@ -2799,7 +2799,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP TransferPacket.TransferData.Data = req.AssetInf.Data; TransferPacket.TransferData.Status = 1; TransferPacket.Header.Zerocoded = true; - OutPacket(TransferPacket, isWearable ? ThrottleOutPacketType.State : ThrottleOutPacketType.Asset); + OutPacket(TransferPacket, isWearable ? ThrottleOutPacketType.Task : ThrottleOutPacketType.Asset); } else { @@ -2832,7 +2832,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP TransferPacket.TransferData.Status = 1; } TransferPacket.Header.Zerocoded = true; - OutPacket(TransferPacket, isWearable ? ThrottleOutPacketType.State : ThrottleOutPacketType.Asset); + OutPacket(TransferPacket, isWearable ? ThrottleOutPacketType.Task : ThrottleOutPacketType.Asset); processedLength += chunkSize; packetNumber++; @@ -3605,7 +3605,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } - OutPacket(aw, ThrottleOutPacketType.State); + OutPacket(aw, ThrottleOutPacketType.Task); } public void SendAppearance(UUID agentID, byte[] visualParams, byte[] textureEntry) @@ -3630,7 +3630,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP avp.Sender.IsTrial = false; avp.Sender.ID = agentID; m_log.DebugFormat("[CLIENT]: Sending appearance for {0} to {1}", agentID.ToString(), AgentId.ToString()); - OutPacket(avp, ThrottleOutPacketType.State); + OutPacket(avp, ThrottleOutPacketType.Task); } public void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs) From 582cb89beb597247ceb6d82cdfc8fc983ffe8496 Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 16 Jan 2013 19:29:27 +0100 Subject: [PATCH 10/10] Add a way to put things at the front of the queue for any throttle group. Adds a DoubleLocklessQueue and uses it for the outgoing buckets. Added a flag value to the Throttle Type (again) because although it's hacky, it's the best of a bad bunch to get the message through the UDP stack to where it's needed. --- OpenSim/Framework/LocklessQueue.cs | 8 +-- OpenSim/Framework/ThrottleOutPacketType.cs | 2 + .../ClientStack/Linden/UDP/LLClientView.cs | 8 +-- .../ClientStack/Linden/UDP/LLUDPClient.cs | 54 +++++++++++++++---- .../ClientStack/Linden/UDP/LLUDPServer.cs | 10 +++- 5 files changed, 63 insertions(+), 19 deletions(-) diff --git a/OpenSim/Framework/LocklessQueue.cs b/OpenSim/Framework/LocklessQueue.cs index 84f887cc4d..9bd9baf321 100644 --- a/OpenSim/Framework/LocklessQueue.cs +++ b/OpenSim/Framework/LocklessQueue.cs @@ -29,7 +29,7 @@ using System.Threading; namespace OpenSim.Framework { - public sealed class LocklessQueue + public class LocklessQueue { private sealed class SingleLinkNode { @@ -41,7 +41,7 @@ namespace OpenSim.Framework SingleLinkNode tail; int count; - public int Count { get { return count; } } + public virtual int Count { get { return count; } } public LocklessQueue() { @@ -76,7 +76,7 @@ namespace OpenSim.Framework Interlocked.Increment(ref count); } - public bool Dequeue(out T item) + public virtual bool Dequeue(out T item) { item = default(T); SingleLinkNode oldHead = null; @@ -136,4 +136,4 @@ namespace OpenSim.Framework (object)Interlocked.CompareExchange(ref location, newValue, comparand); } } -} \ No newline at end of file +} diff --git a/OpenSim/Framework/ThrottleOutPacketType.cs b/OpenSim/Framework/ThrottleOutPacketType.cs index ca4b126c97..87899f0870 100644 --- a/OpenSim/Framework/ThrottleOutPacketType.cs +++ b/OpenSim/Framework/ThrottleOutPacketType.cs @@ -47,6 +47,8 @@ namespace OpenSim.Framework Texture = 5, /// Non-texture assets Asset = 6, + + HighPriority = 128, } [Flags] diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 956c2c9377..9550b5ab8d 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -2788,7 +2788,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP Transfer.TransferInfo.Size = req.AssetInf.Data.Length; Transfer.TransferInfo.TransferID = req.TransferRequestID; Transfer.Header.Zerocoded = true; - OutPacket(Transfer, isWearable ? ThrottleOutPacketType.Task : ThrottleOutPacketType.Asset); + OutPacket(Transfer, isWearable ? ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority : ThrottleOutPacketType.Asset); if (req.NumPackets == 1) { @@ -2799,7 +2799,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP TransferPacket.TransferData.Data = req.AssetInf.Data; TransferPacket.TransferData.Status = 1; TransferPacket.Header.Zerocoded = true; - OutPacket(TransferPacket, isWearable ? ThrottleOutPacketType.Task : ThrottleOutPacketType.Asset); + OutPacket(TransferPacket, isWearable ? ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority : ThrottleOutPacketType.Asset); } else { @@ -2832,7 +2832,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP TransferPacket.TransferData.Status = 1; } TransferPacket.Header.Zerocoded = true; - OutPacket(TransferPacket, isWearable ? ThrottleOutPacketType.Task : ThrottleOutPacketType.Asset); + OutPacket(TransferPacket, isWearable ? ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority : ThrottleOutPacketType.Asset); processedLength += chunkSize; packetNumber++; @@ -3605,7 +3605,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } - OutPacket(aw, ThrottleOutPacketType.Task); + OutPacket(aw, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority); } public void SendAppearance(UUID agentID, byte[] visualParams, byte[] textureEntry) diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs index f1a181209a..e52ac37466 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs @@ -92,7 +92,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// Packets we have sent that need to be ACKed by the client public readonly UnackedPacketCollection NeedAcks = new UnackedPacketCollection(); /// ACKs that are queued up, waiting to be sent to the client - public readonly OpenSim.Framework.LocklessQueue PendingAcks = new OpenSim.Framework.LocklessQueue(); + public readonly DoubleLocklessQueue PendingAcks = new DoubleLocklessQueue(); /// Current packet sequence number public int CurrentSequence; @@ -146,7 +146,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// Throttle buckets for each packet category private readonly TokenBucket[] m_throttleCategories; /// Outgoing queues for throttled packets - private readonly OpenSim.Framework.LocklessQueue[] m_packetOutboxes = new OpenSim.Framework.LocklessQueue[THROTTLE_CATEGORY_COUNT]; + private readonly DoubleLocklessQueue[] m_packetOutboxes = new DoubleLocklessQueue[THROTTLE_CATEGORY_COUNT]; /// A container that can hold one packet for each outbox, used to store /// dequeued packets that are being held for throttling private readonly OutgoingPacket[] m_nextPackets = new OutgoingPacket[THROTTLE_CATEGORY_COUNT]; @@ -202,7 +202,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP ThrottleOutPacketType type = (ThrottleOutPacketType)i; // Initialize the packet outboxes, where packets sit while they are waiting for tokens - m_packetOutboxes[i] = new OpenSim.Framework.LocklessQueue(); + m_packetOutboxes[i] = new DoubleLocklessQueue(); // Initialize the token buckets that control the throttling for each category m_throttleCategories[i] = new TokenBucket(m_throttleCategory, rates.GetRate(type)); } @@ -429,16 +429,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// false if the packet has not been queued and should be sent immediately. /// public bool EnqueueOutgoing(OutgoingPacket packet, bool forceQueue) + { + return EnqueueOutgoing(packet, forceQueue, false); + } + + public bool EnqueueOutgoing(OutgoingPacket packet, bool forceQueue, bool highPriority) { int category = (int)packet.Category; if (category >= 0 && category < m_packetOutboxes.Length) { - OpenSim.Framework.LocklessQueue queue = m_packetOutboxes[category]; + DoubleLocklessQueue queue = m_packetOutboxes[category]; if (m_deliverPackets == false) { - queue.Enqueue(packet); + queue.Enqueue(packet, highPriority); return true; } @@ -449,7 +454,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // queued packets if (queue.Count > 0) { - queue.Enqueue(packet); + queue.Enqueue(packet, highPriority); return true; } @@ -462,7 +467,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP else { // Force queue specified or not enough tokens in the bucket, queue this packet - queue.Enqueue(packet); + queue.Enqueue(packet, highPriority); return true; } } @@ -494,7 +499,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (m_deliverPackets == false) return false; OutgoingPacket packet = null; - OpenSim.Framework.LocklessQueue queue; + DoubleLocklessQueue queue; TokenBucket bucket; bool packetSent = false; ThrottleOutPacketTypeFlags emptyCategories = 0; @@ -534,7 +539,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP } catch { - m_packetOutboxes[i] = new OpenSim.Framework.LocklessQueue(); + m_packetOutboxes[i] = new DoubleLocklessQueue(); } if (success) { @@ -567,7 +572,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP } else { - m_packetOutboxes[i] = new OpenSim.Framework.LocklessQueue(); + m_packetOutboxes[i] = new DoubleLocklessQueue(); emptyCategories |= CategoryToFlag(i); } } @@ -724,4 +729,33 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } } + + public class DoubleLocklessQueue : OpenSim.Framework.LocklessQueue + { + OpenSim.Framework.LocklessQueue highQueue = new OpenSim.Framework.LocklessQueue(); + + public override int Count + { + get + { + return base.Count + highQueue.Count; + } + } + + public override bool Dequeue(out T item) + { + if (highQueue.Dequeue(out item)) + return true; + + return base.Dequeue(out item); + } + + public void Enqueue(T item, bool highPriority) + { + if (highPriority) + highQueue.Enqueue(item); + else + Enqueue(item); + } + } } diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index 9a4abd4877..6c72edca08 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs @@ -803,6 +803,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP #region Queue or Send + bool highPriority = false; + + if (category != ThrottleOutPacketType.Unknown && (category & ThrottleOutPacketType.HighPriority) != 0) + { + category = (ThrottleOutPacketType)((int)category & 127); + highPriority = true; + } + OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category, null); // If we were not provided a method for handling unacked, use the UDPServer default method outgoingPacket.UnackedMethod = ((method == null) ? delegate(OutgoingPacket oPacket) { ResendUnacked(oPacket); } : method); @@ -811,7 +819,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // continue to display the deleted object until relog. Therefore, we need to always queue a kill object // packet so that it isn't sent before a queued update packet. bool requestQueue = type == PacketType.KillObject; - if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, requestQueue)) + if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, requestQueue, highPriority)) SendPacketFinal(outgoingPacket); #endregion Queue or Send