diff --git a/OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs b/OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs index da59294ba6..380705f9ee 100644 --- a/OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs +++ b/OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs @@ -152,6 +152,7 @@ namespace OpenSim.Capabilities.Handlers responsedata["keepalive"] = false; responsedata["str_response_string"] = "This range doesnt exist."; responsedata["reusecontext"] = false; + responsedata["int_lod"] = 3; return responsedata; } else @@ -162,14 +163,28 @@ namespace OpenSim.Capabilities.Handlers //m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID); - + if (start > 20000) + { + responsedata["int_lod"] = 3; + } + else if (start < 4097) + { + responsedata["int_lod"] = 1; + } + else + { + responsedata["int_lod"] = 2; + } + if (start == 0 && len == mesh.Data.Length) // well redudante maybe { responsedata["int_response_code"] = (int) System.Net.HttpStatusCode.OK; responsedata["bin_response_data"] = mesh.Data; responsedata["int_bytes"] = mesh.Data.Length; responsedata["reusecontext"] = false; + responsedata["int_lod"] = 3; + } else { @@ -193,6 +208,7 @@ namespace OpenSim.Capabilities.Handlers responsedata["content_type"] = "application/vnd.ll.mesh"; responsedata["int_response_code"] = 200; responsedata["reusecontext"] = false; + responsedata["int_lod"] = 3; } } else @@ -201,6 +217,7 @@ namespace OpenSim.Capabilities.Handlers responsedata["content_type"] = "application/vnd.ll.mesh"; responsedata["int_response_code"] = 200; responsedata["reusecontext"] = false; + responsedata["int_lod"] = 3; } } // Optionally add additional mesh types here @@ -211,6 +228,7 @@ namespace OpenSim.Capabilities.Handlers responsedata["keepalive"] = false; responsedata["str_response_string"] = "Unfortunately, this asset isn't a mesh."; responsedata["reusecontext"] = false; + responsedata["int_lod"] = 1; return responsedata; } } @@ -221,6 +239,7 @@ namespace OpenSim.Capabilities.Handlers responsedata["keepalive"] = false; responsedata["str_response_string"] = "Your Mesh wasn't found. Sorry!"; responsedata["reusecontext"] = false; + responsedata["int_lod"] = 0; return responsedata; } } diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index 1c6685aec6..f686c6035d 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs @@ -1175,6 +1175,8 @@ namespace OpenSim.Framework void SetChildAgentThrottle(byte[] throttle); + void SetAgentThrottleSilent(int throttle, int setting); + void SendAvatarDataImmediate(ISceneEntity avatar); /// diff --git a/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs index e6d7db8bd8..d2c2ab268d 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs @@ -60,6 +60,7 @@ namespace OpenSim.Region.ClientStack.Linden private IAssetService m_AssetService; private bool m_Enabled = true; private string m_URL; + struct aPollRequest { public PollServiceMeshEventArgs thepoll; @@ -71,6 +72,7 @@ namespace OpenSim.Region.ClientStack.Linden { public Hashtable response; public int bytes; + public int lod; } @@ -112,6 +114,7 @@ namespace OpenSim.Region.ClientStack.Linden // Cap doesn't exist if (m_URL != string.Empty) m_Enabled = true; + } public void AddRegion(Scene pScene) @@ -192,7 +195,7 @@ namespace OpenSim.Region.ClientStack.Linden PollServiceMeshEventArgs args; if (m_pollservices.TryGetValue(user, out args)) { - args.UpdateThrottle(imagethrottle); + args.UpdateThrottle(imagethrottle, p); } } @@ -242,11 +245,12 @@ namespace OpenSim.Region.ClientStack.Linden new Dictionary(); private Scene m_scene; - private CapsDataThrottler m_throttler = new CapsDataThrottler(100000, 1400000, 10000); + private MeshCapsDataThrottler m_throttler; public PollServiceMeshEventArgs(UUID pId, Scene scene) : base(null, null, null, null, pId, int.MaxValue) { m_scene = scene; + m_throttler = new MeshCapsDataThrottler(100000, 1400000, 10000, scene); // x is request id, y is userid HasEvents = (x, y) => { @@ -268,6 +272,7 @@ namespace OpenSim.Region.ClientStack.Linden } finally { + m_throttler.ProcessTime(); responses.Remove(x); } } @@ -323,7 +328,7 @@ namespace OpenSim.Region.ClientStack.Linden response["reusecontext"] = false; lock (responses) - responses[requestID] = new aPollResponse() { bytes = 0, response = response }; + responses[requestID] = new aPollResponse() { bytes = 0, response = response, lod = 0 }; return; } @@ -334,6 +339,7 @@ namespace OpenSim.Region.ClientStack.Linden responses[requestID] = new aPollResponse() { bytes = (int)response["int_bytes"], + lod = (int)response["int_lod"], response = response }; @@ -341,9 +347,9 @@ namespace OpenSim.Region.ClientStack.Linden m_throttler.ProcessTime(); } - internal void UpdateThrottle(int pimagethrottle) + internal void UpdateThrottle(int pimagethrottle, ScenePresence p) { - m_throttler.ThrottleBytes = pimagethrottle; + m_throttler.UpdateThrottle(pimagethrottle, p); } } @@ -398,18 +404,31 @@ namespace OpenSim.Region.ClientStack.Linden } } - internal sealed class CapsDataThrottler + internal sealed class MeshCapsDataThrottler { private volatile int currenttime = 0; private volatile int lastTimeElapsed = 0; private volatile int BytesSent = 0; - private int oversizedImages = 0; - public CapsDataThrottler(int pBytes, int max, int min) + private int Lod3 = 0; + private int Lod2 = 0; + private int Lod1 = 0; + private int UserSetThrottle = 0; + private int UDPSetThrottle = 0; + private int CapSetThrottle = 0; + private float CapThrottleDistributon = 0.30f; + private readonly Scene m_scene; + private ThrottleOutPacketType Throttle; + + public MeshCapsDataThrottler(int pBytes, int max, int min, Scene pScene) { ThrottleBytes = pBytes; lastTimeElapsed = Util.EnvironmentTickCount(); + Throttle = ThrottleOutPacketType.Task; + m_scene = pScene; } + + public bool hasEvents(UUID key, Dictionary responses) { PassTime(); @@ -427,17 +446,23 @@ namespace OpenSim.Region.ClientStack.Linden if (BytesSent + response.bytes <= ThrottleBytes) { BytesSent += response.bytes; - //TimeBasedAction timeBasedAction = new TimeBasedAction { byteRemoval = response.bytes, requestId = key, timeMS = currenttime + 1000, unlockyn = false }; - //m_actions.Add(timeBasedAction); + return true; } - // Big textures - else if (response.bytes > ThrottleBytes && oversizedImages <= ((ThrottleBytes % 50000) + 1)) + // Lod3 Over + else if (response.bytes > ThrottleBytes && Lod3 <= (((ThrottleBytes * .30f) % 50000) + 1)) { - Interlocked.Increment(ref oversizedImages); + Interlocked.Increment(ref Lod3); BytesSent += response.bytes; - //TimeBasedAction timeBasedAction = new TimeBasedAction { byteRemoval = response.bytes, requestId = key, timeMS = currenttime + (((response.bytes % ThrottleBytes)+1)*1000) , unlockyn = false }; - //m_actions.Add(timeBasedAction); + + return true; + } + // Lod2 Over + else if (response.bytes > ThrottleBytes && Lod2 <= (((ThrottleBytes * .30f) % 10000) + 1)) + { + Interlocked.Increment(ref Lod2); + BytesSent += response.bytes; + return true; } else @@ -448,6 +473,11 @@ namespace OpenSim.Region.ClientStack.Linden return haskey; } + public void SubtractBytes(int bytes,int lod) + { + BytesSent -= bytes; + } + public void ProcessTime() { PassTime(); @@ -459,18 +489,42 @@ namespace OpenSim.Region.ClientStack.Linden currenttime = Util.EnvironmentTickCount(); int timeElapsed = Util.EnvironmentTickCountSubtract(currenttime, lastTimeElapsed); //processTimeBasedActions(responses); - if (Util.EnvironmentTickCountSubtract(currenttime, timeElapsed) >= 1000) + if (currenttime - timeElapsed >= 1000) { lastTimeElapsed = Util.EnvironmentTickCount(); BytesSent -= ThrottleBytes; if (BytesSent < 0) BytesSent = 0; if (BytesSent < ThrottleBytes) { - oversizedImages = 0; + Lod3 = 0; + Lod2 = 0; + Lod1 = 0; } } } - public int ThrottleBytes; + private void AlterThrottle(int setting, ScenePresence p) + { + p.ControllingClient.SetAgentThrottleSilent((int)Throttle,setting); + } + + public int ThrottleBytes + { + get { return CapSetThrottle; } + set { CapSetThrottle = value; } + } + + internal void UpdateThrottle(int pimagethrottle, ScenePresence p) + { + // Client set throttle ! + UserSetThrottle = pimagethrottle; + CapSetThrottle = (int)(pimagethrottle*CapThrottleDistributon); + UDPSetThrottle = (int) (pimagethrottle*(100 - CapThrottleDistributon)); + if (CapSetThrottle < 4068) + CapSetThrottle = 4068; // at least two discovery mesh + p.ControllingClient.SetAgentThrottleSilent((int) Throttle, UDPSetThrottle); + ProcessTime(); + + } } } diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 5551f510ba..8e0b72fe50 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -11919,6 +11919,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } + /// + /// Sets the throttles from values supplied by the client + /// + /// + public void SetAgentThrottleSilent(int throttle, int setting) + { + m_udpClient.ForceThrottleSetting(throttle,setting); + //m_udpClient.SetThrottles(throttles); + + } + + /// /// Get the current throttles for this client as a packed byte array /// diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs index c472176933..f675377083 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs @@ -682,6 +682,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (m_nextOnQueueEmpty == 0) m_nextOnQueueEmpty = 1; } + internal void ForceThrottleSetting(int throttle, int setting) + { + m_throttleCategories[throttle].RequestedDripRate = Math.Max(setting, LLUDPServer.MTU); ; + } /// /// Converts a integer to a diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs index 254eeb4d89..a31ccacdb1 100644 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs @@ -1429,6 +1429,11 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server } + public void SetAgentThrottleSilent(int throttle, int setting) + { + + + } public byte[] GetThrottlesPacked(float multiplier) { return new byte[0]; diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs index 3a03101751..d665126e95 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs @@ -596,6 +596,12 @@ namespace OpenSim.Region.OptionalModules.World.NPC public virtual void SetChildAgentThrottle(byte[] throttle) { + } + + public void SetAgentThrottleSilent(int throttle, int setting) + { + + } public byte[] GetThrottlesPacked(float multiplier) { diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs index 5ad3c9f635..2714429ea7 100644 --- a/OpenSim/Tests/Common/Mock/TestClient.cs +++ b/OpenSim/Tests/Common/Mock/TestClient.cs @@ -520,6 +520,12 @@ namespace OpenSim.Tests.Common.Mock public virtual void SetChildAgentThrottle(byte[] throttle) { + } + + public void SetAgentThrottleSilent(int throttle, int setting) + { + + } public byte[] GetThrottlesPacked(float multiplier) {